interceptions](./aibridge_interceptions.md) | Manage AIBridge interceptions. |
diff --git a/docs/reference/cli/aibridge_interceptions.md b/docs/reference/cli/aibridge_interceptions.md
new file mode 100644
index 0000000000000..9cfb3d45a74ea
--- /dev/null
+++ b/docs/reference/cli/aibridge_interceptions.md
@@ -0,0 +1,16 @@
+
+# aibridge interceptions
+
+Manage AIBridge interceptions.
+
+## Usage
+
+```console
+coder aibridge interceptions
+```
+
+## Subcommands
+
+| Name | Purpose |
+|-------------------------------------------------------|--------------------------------------|
+| [list](./aibridge_interceptions_list.md) | List AIBridge interceptions as JSON. |
diff --git a/docs/reference/cli/aibridge_interceptions_list.md b/docs/reference/cli/aibridge_interceptions_list.md
new file mode 100644
index 0000000000000..7e86cd4968e33
--- /dev/null
+++ b/docs/reference/cli/aibridge_interceptions_list.md
@@ -0,0 +1,69 @@
+
+# aibridge interceptions list
+
+List AIBridge interceptions as JSON.
+
+## Usage
+
+```console
+coder aibridge interceptions list [flags]
+```
+
+## Options
+
+### --initiator
+
+| | |
+|------|---------------------|
+| Type | string |
+
+Only return interceptions initiated by this user. Accepts a user ID, username, or "me".
+
+### --started-before
+
+| | |
+|------|---------------------|
+| Type | string |
+
+Only return interceptions started before this time. Must be after 'started-after' if set. Accepts a time in the RFC 3339 format, e.g. "2006-01-02T15:04:05Z07:00".
+
+### --started-after
+
+| | |
+|------|---------------------|
+| Type | string |
+
+Only return interceptions started after this time. Must be before 'started-before' if set. Accepts a time in the RFC 3339 format, e.g. "2006-01-02T15:04:05Z07:00".
+
+### --provider
+
+| | |
+|------|---------------------|
+| Type | string |
+
+Only return interceptions from this provider.
+
+### --model
+
+| | |
+|------|---------------------|
+| Type | string |
+
+Only return interceptions from this model.
+
+### --after-id
+
+| | |
+|------|---------------------|
+| Type | string |
+
+The ID of the last result on the previous page to use as a pagination cursor.
+
+### --limit
+
+| | |
+|---------|------------------|
+| Type | int |
+| Default | 100 |
+
+The limit of results to return. Must be between 1 and 1000.
diff --git a/docs/reference/cli/index.md b/docs/reference/cli/index.md
index c298f8bcb61a2..c1410b4599977 100644
--- a/docs/reference/cli/index.md
+++ b/docs/reference/cli/index.md
@@ -68,6 +68,7 @@ Coder — A tool for provisioning self-hosted development environments with Terr
| [groups](./groups.md) | Manage groups |
| [prebuilds](./prebuilds.md) | Manage Coder prebuilds |
| [external-workspaces](./external-workspaces.md) | Create or manage external workspaces |
+| [aibridge](./aibridge.md) | Manage AIBridge. |
## Options
diff --git a/docs/reference/cli/server.md b/docs/reference/cli/server.md
index bdc424bdd7a8b..e689f7fa28336 100644
--- a/docs/reference/cli/server.md
+++ b/docs/reference/cli/server.md
@@ -1647,3 +1647,108 @@ How often to reconcile workspace prebuilds state.
| Default | false |
Hide AI tasks from the dashboard.
+
+### --aibridge-enabled
+
+| | |
+|-------------|--------------------------------------|
+| Type | bool |
+| Environment | $CODER_AIBRIDGE_ENABLED |
+| YAML | aibridge.enabled |
+| Default | false |
+
+Whether to start an in-memory aibridged instance.
+
+### --aibridge-openai-base-url
+
+| | |
+|-------------|----------------------------------------------|
+| Type | string |
+| Environment | $CODER_AIBRIDGE_OPENAI_BASE_URL |
+| YAML | aibridge.openai_base_url |
+| Default | https://api.openai.com/v1/ |
+
+The base URL of the OpenAI API.
+
+### --aibridge-openai-key
+
+| | |
+|-------------|-----------------------------------------|
+| Type | string |
+| Environment | $CODER_AIBRIDGE_OPENAI_KEY |
+| YAML | aibridge.openai_key |
+
+The key to authenticate against the OpenAI API.
+
+### --aibridge-anthropic-base-url
+
+| | |
+|-------------|-------------------------------------------------|
+| Type | string |
+| Environment | $CODER_AIBRIDGE_ANTHROPIC_BASE_URL |
+| YAML | aibridge.anthropic_base_url |
+| Default | https://api.anthropic.com/ |
+
+The base URL of the Anthropic API.
+
+### --aibridge-anthropic-key
+
+| | |
+|-------------|--------------------------------------------|
+| Type | string |
+| Environment | $CODER_AIBRIDGE_ANTHROPIC_KEY |
+| YAML | aibridge.anthropic_key |
+
+The key to authenticate against the Anthropic API.
+
+### --aibridge-bedrock-region
+
+| | |
+|-------------|---------------------------------------------|
+| Type | string |
+| Environment | $CODER_AIBRIDGE_BEDROCK_REGION |
+| YAML | aibridge.bedrock_region |
+
+The AWS Bedrock API region.
+
+### --aibridge-bedrock-access-key
+
+| | |
+|-------------|-------------------------------------------------|
+| Type | string |
+| Environment | $CODER_AIBRIDGE_BEDROCK_ACCESS_KEY |
+| YAML | aibridge.bedrock_access_key |
+
+The access key to authenticate against the AWS Bedrock API.
+
+### --aibridge-bedrock-access-key-secret
+
+| | |
+|-------------|--------------------------------------------------------|
+| Type | string |
+| Environment | $CODER_AIBRIDGE_BEDROCK_ACCESS_KEY_SECRET |
+| YAML | aibridge.bedrock_access_key_secret |
+
+The access key secret to use with the access key to authenticate against the AWS Bedrock API.
+
+### --aibridge-bedrock-model
+
+| | |
+|-------------|---------------------------------------------------------------|
+| Type | string |
+| Environment | $CODER_AIBRIDGE_BEDROCK_MODEL |
+| YAML | aibridge.bedrock_model |
+| Default | global.anthropic.claude-sonnet-4-5-20250929-v1:0 |
+
+The model to use when making requests to the AWS Bedrock API.
+
+### --aibridge-bedrock-small-fastmodel
+
+| | |
+|-------------|--------------------------------------------------------------|
+| Type | string |
+| Environment | $CODER_AIBRIDGE_BEDROCK_SMALL_FAST_MODEL |
+| YAML | aibridge.bedrock_small_fast_model |
+| Default | global.anthropic.claude-haiku-4-5-20251001-v1:0 |
+
+The small fast model to use when making requests to the AWS Bedrock API. Claude Code uses Haiku-class models to perform background tasks. See https://docs.claude.com/en/docs/claude-code/settings#environment-variables.
diff --git a/dogfood/coder/main.tf b/dogfood/coder/main.tf
index 05ec4a6a2e975..37a53349bb903 100644
--- a/dogfood/coder/main.tf
+++ b/dogfood/coder/main.tf
@@ -479,7 +479,7 @@ resource "coder_agent" "dev" {
dir = local.repo_dir
env = {
OIDC_TOKEN : data.coder_workspace_owner.me.oidc_access_token,
- ANTHROPIC_BASE_URL : "https://dev.coder.com/api/experimental/aibridge/anthropic",
+ ANTHROPIC_BASE_URL : "https://dev.coder.com/api/v2/aibridge/anthropic",
ANTHROPIC_AUTH_TOKEN : data.coder_workspace_owner.me.session_token
}
startup_script_behavior = "blocking"
diff --git a/enterprise/x/aibridged/aibridged.go b/enterprise/aibridged/aibridged.go
similarity index 97%
rename from enterprise/x/aibridged/aibridged.go
rename to enterprise/aibridged/aibridged.go
index a1fa4022ff960..fcec1629b8701 100644
--- a/enterprise/x/aibridged/aibridged.go
+++ b/enterprise/aibridged/aibridged.go
@@ -19,7 +19,7 @@ var _ io.Closer = &Server{}
// Server provides the AI Bridge functionality.
// It is responsible for:
-// - receiving requests on /api/experimental/aibridged/* // TODO: update endpoint once out of experimental
+// - receiving requests on /api/v2/aibridged/*
// - manipulating the requests
// - relaying requests to upstream AI services and relaying responses to caller
//
diff --git a/enterprise/x/aibridged/aibridged_integration_test.go b/enterprise/aibridged/aibridged_integration_test.go
similarity index 99%
rename from enterprise/x/aibridged/aibridged_integration_test.go
rename to enterprise/aibridged/aibridged_integration_test.go
index 45d47bd1b3507..88fa21377f5a2 100644
--- a/enterprise/x/aibridged/aibridged_integration_test.go
+++ b/enterprise/aibridged/aibridged_integration_test.go
@@ -19,8 +19,8 @@ import (
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/coderd/externalauth"
"github.com/coder/coder/v2/codersdk"
+ "github.com/coder/coder/v2/enterprise/aibridged"
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
- "github.com/coder/coder/v2/enterprise/x/aibridged"
"github.com/coder/coder/v2/testutil"
)
diff --git a/enterprise/x/aibridged/aibridged_test.go b/enterprise/aibridged/aibridged_test.go
similarity index 98%
rename from enterprise/x/aibridged/aibridged_test.go
rename to enterprise/aibridged/aibridged_test.go
index 967e9aac2bce3..5d38b7f54d18c 100644
--- a/enterprise/x/aibridged/aibridged_test.go
+++ b/enterprise/aibridged/aibridged_test.go
@@ -18,9 +18,9 @@ import (
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/aibridge"
"github.com/coder/coder/v2/codersdk"
- "github.com/coder/coder/v2/enterprise/x/aibridged"
- mock "github.com/coder/coder/v2/enterprise/x/aibridged/aibridgedmock"
- "github.com/coder/coder/v2/enterprise/x/aibridged/proto"
+ "github.com/coder/coder/v2/enterprise/aibridged"
+ mock "github.com/coder/coder/v2/enterprise/aibridged/aibridgedmock"
+ "github.com/coder/coder/v2/enterprise/aibridged/proto"
"github.com/coder/coder/v2/testutil"
)
diff --git a/enterprise/x/aibridged/aibridgedmock/clientmock.go b/enterprise/aibridged/aibridgedmock/clientmock.go
similarity index 97%
rename from enterprise/x/aibridged/aibridgedmock/clientmock.go
rename to enterprise/aibridged/aibridgedmock/clientmock.go
index c49a385451a8e..2bb7083e10924 100644
--- a/enterprise/x/aibridged/aibridgedmock/clientmock.go
+++ b/enterprise/aibridged/aibridgedmock/clientmock.go
@@ -1,9 +1,9 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: github.com/coder/coder/v2/enterprise/x/aibridged (interfaces: DRPCClient)
+// Source: github.com/coder/coder/v2/enterprise/aibridged (interfaces: DRPCClient)
//
// Generated by this command:
//
-// mockgen -destination ./clientmock.go -package aibridgedmock github.com/coder/coder/v2/enterprise/x/aibridged DRPCClient
+// mockgen -destination ./clientmock.go -package aibridgedmock github.com/coder/coder/v2/enterprise/aibridged DRPCClient
//
// Package aibridgedmock is a generated GoMock package.
@@ -13,7 +13,7 @@ import (
context "context"
reflect "reflect"
- proto "github.com/coder/coder/v2/enterprise/x/aibridged/proto"
+ proto "github.com/coder/coder/v2/enterprise/aibridged/proto"
gomock "go.uber.org/mock/gomock"
drpc "storj.io/drpc"
)
diff --git a/enterprise/x/aibridged/aibridgedmock/doc.go b/enterprise/aibridged/aibridgedmock/doc.go
similarity index 52%
rename from enterprise/x/aibridged/aibridgedmock/doc.go
rename to enterprise/aibridged/aibridgedmock/doc.go
index 3d3f56c05574d..9c9c644570463 100644
--- a/enterprise/x/aibridged/aibridgedmock/doc.go
+++ b/enterprise/aibridged/aibridgedmock/doc.go
@@ -1,4 +1,4 @@
package aibridgedmock
-//go:generate mockgen -destination ./clientmock.go -package aibridgedmock github.com/coder/coder/v2/enterprise/x/aibridged DRPCClient
-//go:generate mockgen -destination ./poolmock.go -package aibridgedmock github.com/coder/coder/v2/enterprise/x/aibridged Pooler
+//go:generate mockgen -destination ./clientmock.go -package aibridgedmock github.com/coder/coder/v2/enterprise/aibridged DRPCClient
+//go:generate mockgen -destination ./poolmock.go -package aibridgedmock github.com/coder/coder/v2/enterprise/aibridged Pooler
diff --git a/enterprise/x/aibridged/aibridgedmock/poolmock.go b/enterprise/aibridged/aibridgedmock/poolmock.go
similarity index 91%
rename from enterprise/x/aibridged/aibridgedmock/poolmock.go
rename to enterprise/aibridged/aibridgedmock/poolmock.go
index bf3b39ed2a879..fcd941fc7c989 100644
--- a/enterprise/x/aibridged/aibridgedmock/poolmock.go
+++ b/enterprise/aibridged/aibridgedmock/poolmock.go
@@ -1,9 +1,9 @@
// Code generated by MockGen. DO NOT EDIT.
-// Source: github.com/coder/coder/v2/enterprise/x/aibridged (interfaces: Pooler)
+// Source: github.com/coder/coder/v2/enterprise/aibridged (interfaces: Pooler)
//
// Generated by this command:
//
-// mockgen -destination ./poolmock.go -package aibridgedmock github.com/coder/coder/v2/enterprise/x/aibridged Pooler
+// mockgen -destination ./poolmock.go -package aibridgedmock github.com/coder/coder/v2/enterprise/aibridged Pooler
//
// Package aibridgedmock is a generated GoMock package.
@@ -14,7 +14,7 @@ import (
http "net/http"
reflect "reflect"
- aibridged "github.com/coder/coder/v2/enterprise/x/aibridged"
+ aibridged "github.com/coder/coder/v2/enterprise/aibridged"
gomock "go.uber.org/mock/gomock"
)
diff --git a/enterprise/x/aibridged/client.go b/enterprise/aibridged/client.go
similarity index 90%
rename from enterprise/x/aibridged/client.go
rename to enterprise/aibridged/client.go
index 3004a84df9626..60650bf994f28 100644
--- a/enterprise/x/aibridged/client.go
+++ b/enterprise/aibridged/client.go
@@ -5,7 +5,7 @@ import (
"storj.io/drpc"
- "github.com/coder/coder/v2/enterprise/x/aibridged/proto"
+ "github.com/coder/coder/v2/enterprise/aibridged/proto"
)
type Dialer func(ctx context.Context) (DRPCClient, error)
diff --git a/enterprise/x/aibridged/http.go b/enterprise/aibridged/http.go
similarity index 98%
rename from enterprise/x/aibridged/http.go
rename to enterprise/aibridged/http.go
index 43f4ba7670671..e87238cc7bbc0 100644
--- a/enterprise/x/aibridged/http.go
+++ b/enterprise/aibridged/http.go
@@ -9,7 +9,7 @@ import (
"cdr.dev/slog"
"github.com/coder/aibridge"
- "github.com/coder/coder/v2/enterprise/x/aibridged/proto"
+ "github.com/coder/coder/v2/enterprise/aibridged/proto"
)
var _ http.Handler = &Server{}
diff --git a/enterprise/x/aibridged/mcp.go b/enterprise/aibridged/mcp.go
similarity index 99%
rename from enterprise/x/aibridged/mcp.go
rename to enterprise/aibridged/mcp.go
index 4b42287e02899..ab6d1d0031d37 100644
--- a/enterprise/x/aibridged/mcp.go
+++ b/enterprise/aibridged/mcp.go
@@ -10,7 +10,7 @@ import (
"cdr.dev/slog"
"github.com/coder/aibridge/mcp"
- "github.com/coder/coder/v2/enterprise/x/aibridged/proto"
+ "github.com/coder/coder/v2/enterprise/aibridged/proto"
)
var (
diff --git a/enterprise/x/aibridged/mcp_internal_test.go b/enterprise/aibridged/mcp_internal_test.go
similarity index 95%
rename from enterprise/x/aibridged/mcp_internal_test.go
rename to enterprise/aibridged/mcp_internal_test.go
index 20edf79d06bf5..37fb6fe2c25d2 100644
--- a/enterprise/x/aibridged/mcp_internal_test.go
+++ b/enterprise/aibridged/mcp_internal_test.go
@@ -5,7 +5,7 @@ import (
"github.com/stretchr/testify/require"
- "github.com/coder/coder/v2/enterprise/x/aibridged/proto"
+ "github.com/coder/coder/v2/enterprise/aibridged/proto"
"github.com/coder/coder/v2/testutil"
)
diff --git a/enterprise/x/aibridged/pool.go b/enterprise/aibridged/pool.go
similarity index 100%
rename from enterprise/x/aibridged/pool.go
rename to enterprise/aibridged/pool.go
diff --git a/enterprise/x/aibridged/pool_test.go b/enterprise/aibridged/pool_test.go
similarity index 96%
rename from enterprise/x/aibridged/pool_test.go
rename to enterprise/aibridged/pool_test.go
index 38cae85da9d92..e3609144f0d59 100644
--- a/enterprise/x/aibridged/pool_test.go
+++ b/enterprise/aibridged/pool_test.go
@@ -13,8 +13,8 @@ import (
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/aibridge/mcp"
"github.com/coder/aibridge/mcpmock"
- "github.com/coder/coder/v2/enterprise/x/aibridged"
- mock "github.com/coder/coder/v2/enterprise/x/aibridged/aibridgedmock"
+ "github.com/coder/coder/v2/enterprise/aibridged"
+ mock "github.com/coder/coder/v2/enterprise/aibridged/aibridgedmock"
)
// TestPool validates the published behavior of [aibridged.CachedBridgePool].
diff --git a/enterprise/x/aibridged/proto/aibridged.pb.go b/enterprise/aibridged/proto/aibridged.pb.go
similarity index 60%
rename from enterprise/x/aibridged/proto/aibridged.pb.go
rename to enterprise/aibridged/proto/aibridged.pb.go
index 41d31563b4043..a13a39ed95245 100644
--- a/enterprise/x/aibridged/proto/aibridged.pb.go
+++ b/enterprise/aibridged/proto/aibridged.pb.go
@@ -2,7 +2,7 @@
// versions:
// protoc-gen-go v1.30.0
// protoc v4.23.4
-// source: enterprise/x/aibridged/proto/aibridged.proto
+// source: enterprise/aibridged/proto/aibridged.proto
package proto
@@ -38,7 +38,7 @@ type RecordInterceptionRequest struct {
func (x *RecordInterceptionRequest) Reset() {
*x = RecordInterceptionRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[0]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -51,7 +51,7 @@ func (x *RecordInterceptionRequest) String() string {
func (*RecordInterceptionRequest) ProtoMessage() {}
func (x *RecordInterceptionRequest) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[0]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -64,7 +64,7 @@ func (x *RecordInterceptionRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use RecordInterceptionRequest.ProtoReflect.Descriptor instead.
func (*RecordInterceptionRequest) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{0}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{0}
}
func (x *RecordInterceptionRequest) GetId() string {
@@ -118,7 +118,7 @@ type RecordInterceptionResponse struct {
func (x *RecordInterceptionResponse) Reset() {
*x = RecordInterceptionResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[1]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -131,7 +131,7 @@ func (x *RecordInterceptionResponse) String() string {
func (*RecordInterceptionResponse) ProtoMessage() {}
func (x *RecordInterceptionResponse) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[1]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -144,7 +144,7 @@ func (x *RecordInterceptionResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use RecordInterceptionResponse.ProtoReflect.Descriptor instead.
func (*RecordInterceptionResponse) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{1}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{1}
}
type RecordInterceptionEndedRequest struct {
@@ -159,7 +159,7 @@ type RecordInterceptionEndedRequest struct {
func (x *RecordInterceptionEndedRequest) Reset() {
*x = RecordInterceptionEndedRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[2]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -172,7 +172,7 @@ func (x *RecordInterceptionEndedRequest) String() string {
func (*RecordInterceptionEndedRequest) ProtoMessage() {}
func (x *RecordInterceptionEndedRequest) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[2]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -185,7 +185,7 @@ func (x *RecordInterceptionEndedRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use RecordInterceptionEndedRequest.ProtoReflect.Descriptor instead.
func (*RecordInterceptionEndedRequest) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{2}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{2}
}
func (x *RecordInterceptionEndedRequest) GetId() string {
@@ -211,7 +211,7 @@ type RecordInterceptionEndedResponse struct {
func (x *RecordInterceptionEndedResponse) Reset() {
*x = RecordInterceptionEndedResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[3]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -224,7 +224,7 @@ func (x *RecordInterceptionEndedResponse) String() string {
func (*RecordInterceptionEndedResponse) ProtoMessage() {}
func (x *RecordInterceptionEndedResponse) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[3]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -237,7 +237,7 @@ func (x *RecordInterceptionEndedResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use RecordInterceptionEndedResponse.ProtoReflect.Descriptor instead.
func (*RecordInterceptionEndedResponse) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{3}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{3}
}
type RecordTokenUsageRequest struct {
@@ -256,7 +256,7 @@ type RecordTokenUsageRequest struct {
func (x *RecordTokenUsageRequest) Reset() {
*x = RecordTokenUsageRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[4]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -269,7 +269,7 @@ func (x *RecordTokenUsageRequest) String() string {
func (*RecordTokenUsageRequest) ProtoMessage() {}
func (x *RecordTokenUsageRequest) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[4]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -282,7 +282,7 @@ func (x *RecordTokenUsageRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use RecordTokenUsageRequest.ProtoReflect.Descriptor instead.
func (*RecordTokenUsageRequest) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{4}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{4}
}
func (x *RecordTokenUsageRequest) GetInterceptionId() string {
@@ -336,7 +336,7 @@ type RecordTokenUsageResponse struct {
func (x *RecordTokenUsageResponse) Reset() {
*x = RecordTokenUsageResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[5]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -349,7 +349,7 @@ func (x *RecordTokenUsageResponse) String() string {
func (*RecordTokenUsageResponse) ProtoMessage() {}
func (x *RecordTokenUsageResponse) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[5]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -362,7 +362,7 @@ func (x *RecordTokenUsageResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use RecordTokenUsageResponse.ProtoReflect.Descriptor instead.
func (*RecordTokenUsageResponse) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{5}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{5}
}
type RecordPromptUsageRequest struct {
@@ -380,7 +380,7 @@ type RecordPromptUsageRequest struct {
func (x *RecordPromptUsageRequest) Reset() {
*x = RecordPromptUsageRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[6]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -393,7 +393,7 @@ func (x *RecordPromptUsageRequest) String() string {
func (*RecordPromptUsageRequest) ProtoMessage() {}
func (x *RecordPromptUsageRequest) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[6]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -406,7 +406,7 @@ func (x *RecordPromptUsageRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use RecordPromptUsageRequest.ProtoReflect.Descriptor instead.
func (*RecordPromptUsageRequest) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{6}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{6}
}
func (x *RecordPromptUsageRequest) GetInterceptionId() string {
@@ -453,7 +453,7 @@ type RecordPromptUsageResponse struct {
func (x *RecordPromptUsageResponse) Reset() {
*x = RecordPromptUsageResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[7]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -466,7 +466,7 @@ func (x *RecordPromptUsageResponse) String() string {
func (*RecordPromptUsageResponse) ProtoMessage() {}
func (x *RecordPromptUsageResponse) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[7]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -479,7 +479,7 @@ func (x *RecordPromptUsageResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use RecordPromptUsageResponse.ProtoReflect.Descriptor instead.
func (*RecordPromptUsageResponse) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{7}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{7}
}
type RecordToolUsageRequest struct {
@@ -501,7 +501,7 @@ type RecordToolUsageRequest struct {
func (x *RecordToolUsageRequest) Reset() {
*x = RecordToolUsageRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[8]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -514,7 +514,7 @@ func (x *RecordToolUsageRequest) String() string {
func (*RecordToolUsageRequest) ProtoMessage() {}
func (x *RecordToolUsageRequest) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[8]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -527,7 +527,7 @@ func (x *RecordToolUsageRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use RecordToolUsageRequest.ProtoReflect.Descriptor instead.
func (*RecordToolUsageRequest) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{8}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{8}
}
func (x *RecordToolUsageRequest) GetInterceptionId() string {
@@ -602,7 +602,7 @@ type RecordToolUsageResponse struct {
func (x *RecordToolUsageResponse) Reset() {
*x = RecordToolUsageResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[9]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -615,7 +615,7 @@ func (x *RecordToolUsageResponse) String() string {
func (*RecordToolUsageResponse) ProtoMessage() {}
func (x *RecordToolUsageResponse) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[9]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -628,7 +628,7 @@ func (x *RecordToolUsageResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use RecordToolUsageResponse.ProtoReflect.Descriptor instead.
func (*RecordToolUsageResponse) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{9}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{9}
}
type GetMCPServerConfigsRequest struct {
@@ -642,7 +642,7 @@ type GetMCPServerConfigsRequest struct {
func (x *GetMCPServerConfigsRequest) Reset() {
*x = GetMCPServerConfigsRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[10]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -655,7 +655,7 @@ func (x *GetMCPServerConfigsRequest) String() string {
func (*GetMCPServerConfigsRequest) ProtoMessage() {}
func (x *GetMCPServerConfigsRequest) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[10]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -668,7 +668,7 @@ func (x *GetMCPServerConfigsRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetMCPServerConfigsRequest.ProtoReflect.Descriptor instead.
func (*GetMCPServerConfigsRequest) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{10}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{10}
}
func (x *GetMCPServerConfigsRequest) GetUserId() string {
@@ -690,7 +690,7 @@ type GetMCPServerConfigsResponse struct {
func (x *GetMCPServerConfigsResponse) Reset() {
*x = GetMCPServerConfigsResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[11]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -703,7 +703,7 @@ func (x *GetMCPServerConfigsResponse) String() string {
func (*GetMCPServerConfigsResponse) ProtoMessage() {}
func (x *GetMCPServerConfigsResponse) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[11]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -716,7 +716,7 @@ func (x *GetMCPServerConfigsResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetMCPServerConfigsResponse.ProtoReflect.Descriptor instead.
func (*GetMCPServerConfigsResponse) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{11}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{11}
}
func (x *GetMCPServerConfigsResponse) GetCoderMcpConfig() *MCPServerConfig {
@@ -747,7 +747,7 @@ type MCPServerConfig struct {
func (x *MCPServerConfig) Reset() {
*x = MCPServerConfig{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[12]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -760,7 +760,7 @@ func (x *MCPServerConfig) String() string {
func (*MCPServerConfig) ProtoMessage() {}
func (x *MCPServerConfig) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[12]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -773,7 +773,7 @@ func (x *MCPServerConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use MCPServerConfig.ProtoReflect.Descriptor instead.
func (*MCPServerConfig) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{12}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{12}
}
func (x *MCPServerConfig) GetId() string {
@@ -816,7 +816,7 @@ type GetMCPServerAccessTokensBatchRequest struct {
func (x *GetMCPServerAccessTokensBatchRequest) Reset() {
*x = GetMCPServerAccessTokensBatchRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[13]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -829,7 +829,7 @@ func (x *GetMCPServerAccessTokensBatchRequest) String() string {
func (*GetMCPServerAccessTokensBatchRequest) ProtoMessage() {}
func (x *GetMCPServerAccessTokensBatchRequest) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[13]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -842,7 +842,7 @@ func (x *GetMCPServerAccessTokensBatchRequest) ProtoReflect() protoreflect.Messa
// Deprecated: Use GetMCPServerAccessTokensBatchRequest.ProtoReflect.Descriptor instead.
func (*GetMCPServerAccessTokensBatchRequest) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{13}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{13}
}
func (x *GetMCPServerAccessTokensBatchRequest) GetUserId() string {
@@ -873,7 +873,7 @@ type GetMCPServerAccessTokensBatchResponse struct {
func (x *GetMCPServerAccessTokensBatchResponse) Reset() {
*x = GetMCPServerAccessTokensBatchResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[14]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -886,7 +886,7 @@ func (x *GetMCPServerAccessTokensBatchResponse) String() string {
func (*GetMCPServerAccessTokensBatchResponse) ProtoMessage() {}
func (x *GetMCPServerAccessTokensBatchResponse) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[14]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -899,7 +899,7 @@ func (x *GetMCPServerAccessTokensBatchResponse) ProtoReflect() protoreflect.Mess
// Deprecated: Use GetMCPServerAccessTokensBatchResponse.ProtoReflect.Descriptor instead.
func (*GetMCPServerAccessTokensBatchResponse) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{14}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{14}
}
func (x *GetMCPServerAccessTokensBatchResponse) GetAccessTokens() map[string]string {
@@ -927,7 +927,7 @@ type IsAuthorizedRequest struct {
func (x *IsAuthorizedRequest) Reset() {
*x = IsAuthorizedRequest{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[15]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -940,7 +940,7 @@ func (x *IsAuthorizedRequest) String() string {
func (*IsAuthorizedRequest) ProtoMessage() {}
func (x *IsAuthorizedRequest) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[15]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -953,7 +953,7 @@ func (x *IsAuthorizedRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use IsAuthorizedRequest.ProtoReflect.Descriptor instead.
func (*IsAuthorizedRequest) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{15}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{15}
}
func (x *IsAuthorizedRequest) GetKey() string {
@@ -974,7 +974,7 @@ type IsAuthorizedResponse struct {
func (x *IsAuthorizedResponse) Reset() {
*x = IsAuthorizedResponse{}
if protoimpl.UnsafeEnabled {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[16]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -987,7 +987,7 @@ func (x *IsAuthorizedResponse) String() string {
func (*IsAuthorizedResponse) ProtoMessage() {}
func (x *IsAuthorizedResponse) ProtoReflect() protoreflect.Message {
- mi := &file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[16]
+ mi := &file_enterprise_aibridged_proto_aibridged_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1000,7 +1000,7 @@ func (x *IsAuthorizedResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use IsAuthorizedResponse.ProtoReflect.Descriptor instead.
func (*IsAuthorizedResponse) Descriptor() ([]byte, []int) {
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{16}
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP(), []int{16}
}
func (x *IsAuthorizedResponse) GetOwnerId() string {
@@ -1010,257 +1010,256 @@ func (x *IsAuthorizedResponse) GetOwnerId() string {
return ""
}
-var File_enterprise_x_aibridged_proto_aibridged_proto protoreflect.FileDescriptor
-
-var file_enterprise_x_aibridged_proto_aibridged_proto_rawDesc = []byte{
- 0x0a, 0x2c, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x2f, 0x78, 0x2f, 0x61,
- 0x69, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61,
- 0x69, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
- 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x22, 0xda, 0x02, 0x0a, 0x19, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65,
- 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
- 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12,
- 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72,
- 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x14,
- 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d,
- 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x4a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
- 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52,
- 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
- 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
- 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
- 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x1a, 0x51, 0x0a, 0x0d, 0x4d,
- 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
- 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a,
- 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e,
- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x1c,
- 0x0a, 0x1a, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70,
- 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x67, 0x0a, 0x1e,
+var File_enterprise_aibridged_proto_aibridged_proto protoreflect.FileDescriptor
+
+var file_enterprise_aibridged_proto_aibridged_proto_rawDesc = []byte{
+ 0x0a, 0x2a, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x2f, 0x61, 0x69, 0x62,
+ 0x72, 0x69, 0x64, 0x67, 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x69, 0x62,
+ 0x72, 0x69, 0x64, 0x67, 0x65, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f,
+ 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f,
+ 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22,
+ 0xda, 0x02, 0x0a, 0x19, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63,
+ 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a,
+ 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a,
+ 0x0c, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x64,
+ 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05,
+ 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x6f, 0x64,
+ 0x65, 0x6c, 0x12, 0x4a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63,
+ 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45,
+ 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x39,
+ 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09,
+ 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x1a, 0x51, 0x0a, 0x0d, 0x4d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
+ 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e,
+ 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x1c, 0x0a, 0x1a,
0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69,
- 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e,
- 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x35,
- 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
- 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e,
- 0x64, 0x65, 0x64, 0x41, 0x74, 0x22, 0x21, 0x0a, 0x1f, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49,
- 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xf9, 0x02, 0x0a, 0x17, 0x52, 0x65, 0x63,
- 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71,
+ 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x67, 0x0a, 0x1e, 0x52, 0x65,
+ 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x45, 0x6e, 0x64, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02,
+ 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x35, 0x0a, 0x08,
+ 0x65, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+ 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x65,
+ 0x64, 0x41, 0x74, 0x22, 0x21, 0x0a, 0x1f, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74,
+ 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xf9, 0x02, 0x0a, 0x17, 0x52, 0x65, 0x63, 0x6f, 0x72,
+ 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x6d,
+ 0x73, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x73, 0x67,
+ 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65,
+ 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54,
+ 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f,
+ 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x75,
+ 0x74, 0x70, 0x75, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x48, 0x0a, 0x08, 0x6d, 0x65,
+ 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70,
+ 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
+ 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f,
+ 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
+ 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x1a,
+ 0x51, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79,
+ 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
+ 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
+ 0x38, 0x01, 0x22, 0x1a, 0x0a, 0x18, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6b, 0x65,
+ 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xcb,
+ 0x02, 0x0a, 0x18, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x55,
+ 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70,
+ 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x72, 0x6f,
+ 0x6d, 0x70, 0x74, 0x12, 0x49, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18,
+ 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65,
+ 0x63, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45,
+ 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x39,
+ 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09,
+ 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x1a, 0x51, 0x0a, 0x0d, 0x4d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
+ 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e,
+ 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x1b, 0x0a, 0x19,
+ 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x55, 0x73, 0x61, 0x67,
+ 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xed, 0x03, 0x0a, 0x16, 0x52, 0x65,
+ 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x15, 0x0a,
0x06, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d,
- 0x73, 0x67, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x6f,
- 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75,
- 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x75, 0x74, 0x70, 0x75,
- 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c,
- 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x48, 0x0a, 0x08,
- 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c,
- 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6b,
- 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d,
- 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65,
- 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
- 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
- 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
- 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41,
- 0x74, 0x1a, 0x51, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74,
- 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x3a, 0x02, 0x38, 0x01, 0x22, 0x1a, 0x0a, 0x18, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f,
- 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x22, 0xcb, 0x02, 0x0a, 0x18, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, 0x6d, 0x70,
- 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a,
- 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70,
- 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x16, 0x0a,
- 0x06, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70,
- 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x49, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
- 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
- 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x55, 0x73, 0x61, 0x67,
- 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
- 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
- 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
- 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x1a, 0x51, 0x0a, 0x0d, 0x4d,
- 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
- 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a,
- 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e,
- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x1b,
- 0x0a, 0x19, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x55, 0x73,
- 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xed, 0x03, 0x0a, 0x16,
- 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63,
- 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x0e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12,
- 0x15, 0x0a, 0x06, 0x6d, 0x73, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x05, 0x6d, 0x73, 0x67, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
- 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x73, 0x65,
- 0x72, 0x76, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x6f,
- 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x12, 0x14,
- 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69,
- 0x6e, 0x70, 0x75, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64,
- 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64,
- 0x12, 0x2e, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65,
- 0x72, 0x72, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, 0x69, 0x6e,
- 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x88, 0x01, 0x01,
- 0x12, 0x47, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x08, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72,
- 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
- 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65,
- 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
- 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
- 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74,
- 0x65, 0x64, 0x41, 0x74, 0x1a, 0x51, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
- 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, 0x61,
- 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x73, 0x65, 0x72, 0x76,
- 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x69, 0x6e, 0x76, 0x6f, 0x63,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x19, 0x0a, 0x17, 0x52,
- 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50,
- 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xb2, 0x01,
- 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a,
- 0x10, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
- 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
- 0x0e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
- 0x51, 0x0a, 0x19, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68,
- 0x5f, 0x6d, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x43, 0x50, 0x53, 0x65,
- 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x16, 0x65, 0x78, 0x74, 0x65,
- 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x73, 0x22, 0x85, 0x01, 0x0a, 0x0f, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
- 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x6f, 0x6c,
- 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x0e, 0x74, 0x6f, 0x6f, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x67,
- 0x65, 0x78, 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x64, 0x65, 0x6e, 0x79, 0x5f,
- 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x6f, 0x6f,
- 0x6c, 0x44, 0x65, 0x6e, 0x79, 0x52, 0x65, 0x67, 0x65, 0x78, 0x22, 0x72, 0x0a, 0x24, 0x47, 0x65,
- 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73,
- 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x67, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x75,
+ 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x6f, 0x6f, 0x6c,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x6f, 0x6f, 0x6c, 0x12, 0x14, 0x0a, 0x05,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6e, 0x70,
+ 0x75, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x06,
+ 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x6e, 0x6a, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x2e,
+ 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72,
+ 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x6f,
+ 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x47,
+ 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54,
+ 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e,
+ 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6d,
+ 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74,
+ 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69,
+ 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
+ 0x41, 0x74, 0x1a, 0x51, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x6e,
+ 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
+ 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
+ 0x5f, 0x75, 0x72, 0x6c, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x19, 0x0a, 0x17, 0x52, 0x65, 0x63,
+ 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65,
+ 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x15, 0x6d,
- 0x63, 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
- 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x6d, 0x63, 0x70, 0x53,
- 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x64, 0x73, 0x22, 0xda,
- 0x02, 0x0a, 0x25, 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41,
- 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x65,
- 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x3e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65,
- 0x72, 0x76, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73,
- 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x63,
- 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
- 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x50, 0x0a,
- 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e,
+ 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xb2, 0x01, 0x0a, 0x1b,
+ 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x10, 0x63,
+ 0x6f, 0x64, 0x65, 0x72, 0x5f, 0x6d, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x43,
+ 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x63,
+ 0x6f, 0x64, 0x65, 0x72, 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x51, 0x0a,
+ 0x19, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d,
+ 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76,
+ 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x16, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e,
+ 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73,
+ 0x22, 0x85, 0x01, 0x0a, 0x0f, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x61,
+ 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0e, 0x74, 0x6f, 0x6f, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x67, 0x65, 0x78,
+ 0x12, 0x26, 0x0a, 0x0f, 0x74, 0x6f, 0x6f, 0x6c, 0x5f, 0x64, 0x65, 0x6e, 0x79, 0x5f, 0x72, 0x65,
+ 0x67, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x6f, 0x6f, 0x6c, 0x44,
+ 0x65, 0x6e, 0x79, 0x52, 0x65, 0x67, 0x65, 0x78, 0x22, 0x72, 0x0a, 0x24, 0x47, 0x65, 0x74, 0x4d,
+ 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f,
+ 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
+ 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x15, 0x6d, 0x63, 0x70,
+ 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69,
+ 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x6d, 0x63, 0x70, 0x53, 0x65, 0x72,
+ 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x64, 0x73, 0x22, 0xda, 0x02, 0x0a,
+ 0x25, 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x63, 0x63,
+ 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73,
+ 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76,
0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x61,
- 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f,
- 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x1a,
- 0x3f, 0x0a, 0x11, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x45,
- 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
- 0x1a, 0x39, 0x0a, 0x0b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
- 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
- 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x27, 0x0a, 0x13, 0x49,
- 0x73, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x03, 0x6b, 0x65, 0x79, 0x22, 0x31, 0x0a, 0x14, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
- 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08,
- 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
- 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x32, 0xce, 0x03, 0x0a, 0x08, 0x52, 0x65, 0x63, 0x6f,
- 0x72, 0x64, 0x65, 0x72, 0x12, 0x59, 0x0a, 0x12, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e,
- 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72,
- 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
- 0x68, 0x0a, 0x17, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x1a, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
- 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x65,
- 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x52, 0x65, 0x63,
- 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6b, 0x65,
- 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e,
- 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6b, 0x65,
- 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56,
- 0x0a, 0x11, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x55, 0x73,
- 0x61, 0x67, 0x65, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f,
- 0x72, 0x64, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63,
- 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
- 0x54, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x61, 0x67,
- 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x61, 0x67, 0x65,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xeb, 0x01, 0x0a, 0x0f, 0x4d, 0x43, 0x50,
- 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x5c, 0x0a, 0x13,
- 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,
- 0x69, 0x67, 0x73, 0x12, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d,
- 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47,
- 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x1d, 0x47, 0x65,
- 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73,
- 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x2b, 0x2e, 0x70, 0x72,
+ 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x63, 0x63, 0x65,
+ 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x61,
+ 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x50, 0x0a, 0x06, 0x65,
+ 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x61, 0x74, 0x63,
- 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x63, 0x63,
- 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x55, 0x0a, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
- 0x69, 0x7a, 0x65, 0x72, 0x12, 0x47, 0x0a, 0x0c, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
- 0x69, 0x7a, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x73, 0x41,
+ 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73,
+ 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x1a, 0x3f, 0x0a,
+ 0x11, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x45, 0x6e, 0x74,
+ 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x39,
+ 0x0a, 0x0b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
+ 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
+ 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x27, 0x0a, 0x13, 0x49, 0x73, 0x41,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x1a, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68, 0x6f,
- 0x72, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2b, 0x5a,
- 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65,
- 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x69, 0x62, 0x72, 0x69,
- 0x64, 0x67, 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x33,
+ 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
+ 0x65, 0x79, 0x22, 0x31, 0x0a, 0x14, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
+ 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x77,
+ 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x77,
+ 0x6e, 0x65, 0x72, 0x49, 0x64, 0x32, 0xce, 0x03, 0x0a, 0x08, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x12, 0x59, 0x0a, 0x12, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a,
+ 0x17, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64, 0x12, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+ 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x65, 0x64, 0x52,
+ 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x10, 0x52, 0x65, 0x63, 0x6f, 0x72,
+ 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55,
+ 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x55,
+ 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x11,
+ 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x55, 0x73, 0x61, 0x67,
+ 0x65, 0x12, 0x1f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
+ 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+ 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72,
+ 0x64, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f,
+ 0x6f, 0x6c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+ 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52,
+ 0x65, 0x63, 0x6f, 0x72, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xeb, 0x01, 0x0a, 0x0f, 0x4d, 0x43, 0x50, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x5c, 0x0a, 0x13, 0x47, 0x65,
+ 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x73, 0x12, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50,
+ 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74,
+ 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x4d,
+ 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f,
+ 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x2b, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x63,
+ 0x63, 0x65, 0x73, 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52,
+ 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47,
+ 0x65, 0x74, 0x4d, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73,
+ 0x73, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70,
+ 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x55, 0x0a, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
+ 0x65, 0x72, 0x12, 0x47, 0x0a, 0x0c, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
+ 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x73, 0x41, 0x75, 0x74,
+ 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b,
+ 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
+ 0x7a, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2b, 0x5a, 0x29, 0x67,
+ 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f,
+ 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x69, 0x62, 0x72, 0x69, 0x64, 0x67,
+ 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
- file_enterprise_x_aibridged_proto_aibridged_proto_rawDescOnce sync.Once
- file_enterprise_x_aibridged_proto_aibridged_proto_rawDescData = file_enterprise_x_aibridged_proto_aibridged_proto_rawDesc
+ file_enterprise_aibridged_proto_aibridged_proto_rawDescOnce sync.Once
+ file_enterprise_aibridged_proto_aibridged_proto_rawDescData = file_enterprise_aibridged_proto_aibridged_proto_rawDesc
)
-func file_enterprise_x_aibridged_proto_aibridged_proto_rawDescGZIP() []byte {
- file_enterprise_x_aibridged_proto_aibridged_proto_rawDescOnce.Do(func() {
- file_enterprise_x_aibridged_proto_aibridged_proto_rawDescData = protoimpl.X.CompressGZIP(file_enterprise_x_aibridged_proto_aibridged_proto_rawDescData)
+func file_enterprise_aibridged_proto_aibridged_proto_rawDescGZIP() []byte {
+ file_enterprise_aibridged_proto_aibridged_proto_rawDescOnce.Do(func() {
+ file_enterprise_aibridged_proto_aibridged_proto_rawDescData = protoimpl.X.CompressGZIP(file_enterprise_aibridged_proto_aibridged_proto_rawDescData)
})
- return file_enterprise_x_aibridged_proto_aibridged_proto_rawDescData
+ return file_enterprise_aibridged_proto_aibridged_proto_rawDescData
}
-var file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes = make([]protoimpl.MessageInfo, 23)
-var file_enterprise_x_aibridged_proto_aibridged_proto_goTypes = []interface{}{
+var file_enterprise_aibridged_proto_aibridged_proto_msgTypes = make([]protoimpl.MessageInfo, 23)
+var file_enterprise_aibridged_proto_aibridged_proto_goTypes = []interface{}{
(*RecordInterceptionRequest)(nil), // 0: proto.RecordInterceptionRequest
(*RecordInterceptionResponse)(nil), // 1: proto.RecordInterceptionResponse
(*RecordInterceptionEndedRequest)(nil), // 2: proto.RecordInterceptionEndedRequest
@@ -1287,7 +1286,7 @@ var file_enterprise_x_aibridged_proto_aibridged_proto_goTypes = []interface{}{
(*timestamppb.Timestamp)(nil), // 23: google.protobuf.Timestamp
(*anypb.Any)(nil), // 24: google.protobuf.Any
}
-var file_enterprise_x_aibridged_proto_aibridged_proto_depIdxs = []int32{
+var file_enterprise_aibridged_proto_aibridged_proto_depIdxs = []int32{
17, // 0: proto.RecordInterceptionRequest.metadata:type_name -> proto.RecordInterceptionRequest.MetadataEntry
23, // 1: proto.RecordInterceptionRequest.started_at:type_name -> google.protobuf.Timestamp
23, // 2: proto.RecordInterceptionEndedRequest.ended_at:type_name -> google.protobuf.Timestamp
@@ -1328,13 +1327,13 @@ var file_enterprise_x_aibridged_proto_aibridged_proto_depIdxs = []int32{
0, // [0:17] is the sub-list for field type_name
}
-func init() { file_enterprise_x_aibridged_proto_aibridged_proto_init() }
-func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
- if File_enterprise_x_aibridged_proto_aibridged_proto != nil {
+func init() { file_enterprise_aibridged_proto_aibridged_proto_init() }
+func file_enterprise_aibridged_proto_aibridged_proto_init() {
+ if File_enterprise_aibridged_proto_aibridged_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RecordInterceptionRequest); i {
case 0:
return &v.state
@@ -1346,7 +1345,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RecordInterceptionResponse); i {
case 0:
return &v.state
@@ -1358,7 +1357,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RecordInterceptionEndedRequest); i {
case 0:
return &v.state
@@ -1370,7 +1369,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RecordInterceptionEndedResponse); i {
case 0:
return &v.state
@@ -1382,7 +1381,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RecordTokenUsageRequest); i {
case 0:
return &v.state
@@ -1394,7 +1393,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RecordTokenUsageResponse); i {
case 0:
return &v.state
@@ -1406,7 +1405,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RecordPromptUsageRequest); i {
case 0:
return &v.state
@@ -1418,7 +1417,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RecordPromptUsageResponse); i {
case 0:
return &v.state
@@ -1430,7 +1429,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RecordToolUsageRequest); i {
case 0:
return &v.state
@@ -1442,7 +1441,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RecordToolUsageResponse); i {
case 0:
return &v.state
@@ -1454,7 +1453,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetMCPServerConfigsRequest); i {
case 0:
return &v.state
@@ -1466,7 +1465,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetMCPServerConfigsResponse); i {
case 0:
return &v.state
@@ -1478,7 +1477,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MCPServerConfig); i {
case 0:
return &v.state
@@ -1490,7 +1489,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetMCPServerAccessTokensBatchRequest); i {
case 0:
return &v.state
@@ -1502,7 +1501,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetMCPServerAccessTokensBatchResponse); i {
case 0:
return &v.state
@@ -1514,7 +1513,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*IsAuthorizedRequest); i {
case 0:
return &v.state
@@ -1526,7 +1525,7 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
return nil
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*IsAuthorizedResponse); i {
case 0:
return &v.state
@@ -1539,23 +1538,23 @@ func file_enterprise_x_aibridged_proto_aibridged_proto_init() {
}
}
}
- file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes[8].OneofWrappers = []interface{}{}
+ file_enterprise_aibridged_proto_aibridged_proto_msgTypes[8].OneofWrappers = []interface{}{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_enterprise_x_aibridged_proto_aibridged_proto_rawDesc,
+ RawDescriptor: file_enterprise_aibridged_proto_aibridged_proto_rawDesc,
NumEnums: 0,
NumMessages: 23,
NumExtensions: 0,
NumServices: 3,
},
- GoTypes: file_enterprise_x_aibridged_proto_aibridged_proto_goTypes,
- DependencyIndexes: file_enterprise_x_aibridged_proto_aibridged_proto_depIdxs,
- MessageInfos: file_enterprise_x_aibridged_proto_aibridged_proto_msgTypes,
+ GoTypes: file_enterprise_aibridged_proto_aibridged_proto_goTypes,
+ DependencyIndexes: file_enterprise_aibridged_proto_aibridged_proto_depIdxs,
+ MessageInfos: file_enterprise_aibridged_proto_aibridged_proto_msgTypes,
}.Build()
- File_enterprise_x_aibridged_proto_aibridged_proto = out.File
- file_enterprise_x_aibridged_proto_aibridged_proto_rawDesc = nil
- file_enterprise_x_aibridged_proto_aibridged_proto_goTypes = nil
- file_enterprise_x_aibridged_proto_aibridged_proto_depIdxs = nil
+ File_enterprise_aibridged_proto_aibridged_proto = out.File
+ file_enterprise_aibridged_proto_aibridged_proto_rawDesc = nil
+ file_enterprise_aibridged_proto_aibridged_proto_goTypes = nil
+ file_enterprise_aibridged_proto_aibridged_proto_depIdxs = nil
}
diff --git a/enterprise/x/aibridged/proto/aibridged.proto b/enterprise/aibridged/proto/aibridged.proto
similarity index 100%
rename from enterprise/x/aibridged/proto/aibridged.proto
rename to enterprise/aibridged/proto/aibridged.proto
diff --git a/enterprise/x/aibridged/proto/aibridged_drpc.pb.go b/enterprise/aibridged/proto/aibridged_drpc.pb.go
similarity index 84%
rename from enterprise/x/aibridged/proto/aibridged_drpc.pb.go
rename to enterprise/aibridged/proto/aibridged_drpc.pb.go
index 4c7cb3c190764..1309957d153d5 100644
--- a/enterprise/x/aibridged/proto/aibridged_drpc.pb.go
+++ b/enterprise/aibridged/proto/aibridged_drpc.pb.go
@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-drpc. DO NOT EDIT.
// protoc-gen-go-drpc version: v0.0.34
-// source: enterprise/x/aibridged/proto/aibridged.proto
+// source: enterprise/aibridged/proto/aibridged.proto
package proto
@@ -13,25 +13,25 @@ import (
drpcerr "storj.io/drpc/drpcerr"
)
-type drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto struct{}
+type drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto struct{}
-func (drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto) Marshal(msg drpc.Message) ([]byte, error) {
+func (drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto) Marshal(msg drpc.Message) ([]byte, error) {
return proto.Marshal(msg.(proto.Message))
}
-func (drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto) MarshalAppend(buf []byte, msg drpc.Message) ([]byte, error) {
+func (drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto) MarshalAppend(buf []byte, msg drpc.Message) ([]byte, error) {
return proto.MarshalOptions{}.MarshalAppend(buf, msg.(proto.Message))
}
-func (drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto) Unmarshal(buf []byte, msg drpc.Message) error {
+func (drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto) Unmarshal(buf []byte, msg drpc.Message) error {
return proto.Unmarshal(buf, msg.(proto.Message))
}
-func (drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto) JSONMarshal(msg drpc.Message) ([]byte, error) {
+func (drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto) JSONMarshal(msg drpc.Message) ([]byte, error) {
return protojson.Marshal(msg.(proto.Message))
}
-func (drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto) JSONUnmarshal(buf []byte, msg drpc.Message) error {
+func (drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto) JSONUnmarshal(buf []byte, msg drpc.Message) error {
return protojson.Unmarshal(buf, msg.(proto.Message))
}
@@ -57,7 +57,7 @@ func (c *drpcRecorderClient) DRPCConn() drpc.Conn { return c.cc }
func (c *drpcRecorderClient) RecordInterception(ctx context.Context, in *RecordInterceptionRequest) (*RecordInterceptionResponse, error) {
out := new(RecordInterceptionResponse)
- err := c.cc.Invoke(ctx, "/proto.Recorder/RecordInterception", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}, in, out)
+ err := c.cc.Invoke(ctx, "/proto.Recorder/RecordInterception", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}, in, out)
if err != nil {
return nil, err
}
@@ -66,7 +66,7 @@ func (c *drpcRecorderClient) RecordInterception(ctx context.Context, in *RecordI
func (c *drpcRecorderClient) RecordInterceptionEnded(ctx context.Context, in *RecordInterceptionEndedRequest) (*RecordInterceptionEndedResponse, error) {
out := new(RecordInterceptionEndedResponse)
- err := c.cc.Invoke(ctx, "/proto.Recorder/RecordInterceptionEnded", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}, in, out)
+ err := c.cc.Invoke(ctx, "/proto.Recorder/RecordInterceptionEnded", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}, in, out)
if err != nil {
return nil, err
}
@@ -75,7 +75,7 @@ func (c *drpcRecorderClient) RecordInterceptionEnded(ctx context.Context, in *Re
func (c *drpcRecorderClient) RecordTokenUsage(ctx context.Context, in *RecordTokenUsageRequest) (*RecordTokenUsageResponse, error) {
out := new(RecordTokenUsageResponse)
- err := c.cc.Invoke(ctx, "/proto.Recorder/RecordTokenUsage", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}, in, out)
+ err := c.cc.Invoke(ctx, "/proto.Recorder/RecordTokenUsage", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}, in, out)
if err != nil {
return nil, err
}
@@ -84,7 +84,7 @@ func (c *drpcRecorderClient) RecordTokenUsage(ctx context.Context, in *RecordTok
func (c *drpcRecorderClient) RecordPromptUsage(ctx context.Context, in *RecordPromptUsageRequest) (*RecordPromptUsageResponse, error) {
out := new(RecordPromptUsageResponse)
- err := c.cc.Invoke(ctx, "/proto.Recorder/RecordPromptUsage", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}, in, out)
+ err := c.cc.Invoke(ctx, "/proto.Recorder/RecordPromptUsage", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}, in, out)
if err != nil {
return nil, err
}
@@ -93,7 +93,7 @@ func (c *drpcRecorderClient) RecordPromptUsage(ctx context.Context, in *RecordPr
func (c *drpcRecorderClient) RecordToolUsage(ctx context.Context, in *RecordToolUsageRequest) (*RecordToolUsageResponse, error) {
out := new(RecordToolUsageResponse)
- err := c.cc.Invoke(ctx, "/proto.Recorder/RecordToolUsage", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}, in, out)
+ err := c.cc.Invoke(ctx, "/proto.Recorder/RecordToolUsage", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}, in, out)
if err != nil {
return nil, err
}
@@ -137,7 +137,7 @@ func (DRPCRecorderDescription) NumMethods() int { return 5 }
func (DRPCRecorderDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) {
switch n {
case 0:
- return "/proto.Recorder/RecordInterception", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{},
+ return "/proto.Recorder/RecordInterception", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCRecorderServer).
RecordInterception(
@@ -146,7 +146,7 @@ func (DRPCRecorderDescription) Method(n int) (string, drpc.Encoding, drpc.Receiv
)
}, DRPCRecorderServer.RecordInterception, true
case 1:
- return "/proto.Recorder/RecordInterceptionEnded", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{},
+ return "/proto.Recorder/RecordInterceptionEnded", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCRecorderServer).
RecordInterceptionEnded(
@@ -155,7 +155,7 @@ func (DRPCRecorderDescription) Method(n int) (string, drpc.Encoding, drpc.Receiv
)
}, DRPCRecorderServer.RecordInterceptionEnded, true
case 2:
- return "/proto.Recorder/RecordTokenUsage", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{},
+ return "/proto.Recorder/RecordTokenUsage", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCRecorderServer).
RecordTokenUsage(
@@ -164,7 +164,7 @@ func (DRPCRecorderDescription) Method(n int) (string, drpc.Encoding, drpc.Receiv
)
}, DRPCRecorderServer.RecordTokenUsage, true
case 3:
- return "/proto.Recorder/RecordPromptUsage", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{},
+ return "/proto.Recorder/RecordPromptUsage", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCRecorderServer).
RecordPromptUsage(
@@ -173,7 +173,7 @@ func (DRPCRecorderDescription) Method(n int) (string, drpc.Encoding, drpc.Receiv
)
}, DRPCRecorderServer.RecordPromptUsage, true
case 4:
- return "/proto.Recorder/RecordToolUsage", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{},
+ return "/proto.Recorder/RecordToolUsage", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCRecorderServer).
RecordToolUsage(
@@ -200,7 +200,7 @@ type drpcRecorder_RecordInterceptionStream struct {
}
func (x *drpcRecorder_RecordInterceptionStream) SendAndClose(m *RecordInterceptionResponse) error {
- if err := x.MsgSend(m, drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}); err != nil {
+ if err := x.MsgSend(m, drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}); err != nil {
return err
}
return x.CloseSend()
@@ -216,7 +216,7 @@ type drpcRecorder_RecordInterceptionEndedStream struct {
}
func (x *drpcRecorder_RecordInterceptionEndedStream) SendAndClose(m *RecordInterceptionEndedResponse) error {
- if err := x.MsgSend(m, drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}); err != nil {
+ if err := x.MsgSend(m, drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}); err != nil {
return err
}
return x.CloseSend()
@@ -232,7 +232,7 @@ type drpcRecorder_RecordTokenUsageStream struct {
}
func (x *drpcRecorder_RecordTokenUsageStream) SendAndClose(m *RecordTokenUsageResponse) error {
- if err := x.MsgSend(m, drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}); err != nil {
+ if err := x.MsgSend(m, drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}); err != nil {
return err
}
return x.CloseSend()
@@ -248,7 +248,7 @@ type drpcRecorder_RecordPromptUsageStream struct {
}
func (x *drpcRecorder_RecordPromptUsageStream) SendAndClose(m *RecordPromptUsageResponse) error {
- if err := x.MsgSend(m, drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}); err != nil {
+ if err := x.MsgSend(m, drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}); err != nil {
return err
}
return x.CloseSend()
@@ -264,7 +264,7 @@ type drpcRecorder_RecordToolUsageStream struct {
}
func (x *drpcRecorder_RecordToolUsageStream) SendAndClose(m *RecordToolUsageResponse) error {
- if err := x.MsgSend(m, drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}); err != nil {
+ if err := x.MsgSend(m, drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}); err != nil {
return err
}
return x.CloseSend()
@@ -289,7 +289,7 @@ func (c *drpcMCPConfiguratorClient) DRPCConn() drpc.Conn { return c.cc }
func (c *drpcMCPConfiguratorClient) GetMCPServerConfigs(ctx context.Context, in *GetMCPServerConfigsRequest) (*GetMCPServerConfigsResponse, error) {
out := new(GetMCPServerConfigsResponse)
- err := c.cc.Invoke(ctx, "/proto.MCPConfigurator/GetMCPServerConfigs", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}, in, out)
+ err := c.cc.Invoke(ctx, "/proto.MCPConfigurator/GetMCPServerConfigs", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}, in, out)
if err != nil {
return nil, err
}
@@ -298,7 +298,7 @@ func (c *drpcMCPConfiguratorClient) GetMCPServerConfigs(ctx context.Context, in
func (c *drpcMCPConfiguratorClient) GetMCPServerAccessTokensBatch(ctx context.Context, in *GetMCPServerAccessTokensBatchRequest) (*GetMCPServerAccessTokensBatchResponse, error) {
out := new(GetMCPServerAccessTokensBatchResponse)
- err := c.cc.Invoke(ctx, "/proto.MCPConfigurator/GetMCPServerAccessTokensBatch", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}, in, out)
+ err := c.cc.Invoke(ctx, "/proto.MCPConfigurator/GetMCPServerAccessTokensBatch", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}, in, out)
if err != nil {
return nil, err
}
@@ -327,7 +327,7 @@ func (DRPCMCPConfiguratorDescription) NumMethods() int { return 2 }
func (DRPCMCPConfiguratorDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) {
switch n {
case 0:
- return "/proto.MCPConfigurator/GetMCPServerConfigs", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{},
+ return "/proto.MCPConfigurator/GetMCPServerConfigs", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCMCPConfiguratorServer).
GetMCPServerConfigs(
@@ -336,7 +336,7 @@ func (DRPCMCPConfiguratorDescription) Method(n int) (string, drpc.Encoding, drpc
)
}, DRPCMCPConfiguratorServer.GetMCPServerConfigs, true
case 1:
- return "/proto.MCPConfigurator/GetMCPServerAccessTokensBatch", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{},
+ return "/proto.MCPConfigurator/GetMCPServerAccessTokensBatch", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCMCPConfiguratorServer).
GetMCPServerAccessTokensBatch(
@@ -363,7 +363,7 @@ type drpcMCPConfigurator_GetMCPServerConfigsStream struct {
}
func (x *drpcMCPConfigurator_GetMCPServerConfigsStream) SendAndClose(m *GetMCPServerConfigsResponse) error {
- if err := x.MsgSend(m, drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}); err != nil {
+ if err := x.MsgSend(m, drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}); err != nil {
return err
}
return x.CloseSend()
@@ -379,7 +379,7 @@ type drpcMCPConfigurator_GetMCPServerAccessTokensBatchStream struct {
}
func (x *drpcMCPConfigurator_GetMCPServerAccessTokensBatchStream) SendAndClose(m *GetMCPServerAccessTokensBatchResponse) error {
- if err := x.MsgSend(m, drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}); err != nil {
+ if err := x.MsgSend(m, drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}); err != nil {
return err
}
return x.CloseSend()
@@ -403,7 +403,7 @@ func (c *drpcAuthorizerClient) DRPCConn() drpc.Conn { return c.cc }
func (c *drpcAuthorizerClient) IsAuthorized(ctx context.Context, in *IsAuthorizedRequest) (*IsAuthorizedResponse, error) {
out := new(IsAuthorizedResponse)
- err := c.cc.Invoke(ctx, "/proto.Authorizer/IsAuthorized", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}, in, out)
+ err := c.cc.Invoke(ctx, "/proto.Authorizer/IsAuthorized", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}, in, out)
if err != nil {
return nil, err
}
@@ -427,7 +427,7 @@ func (DRPCAuthorizerDescription) NumMethods() int { return 1 }
func (DRPCAuthorizerDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) {
switch n {
case 0:
- return "/proto.Authorizer/IsAuthorized", drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{},
+ return "/proto.Authorizer/IsAuthorized", drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{},
func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) {
return srv.(DRPCAuthorizerServer).
IsAuthorized(
@@ -454,7 +454,7 @@ type drpcAuthorizer_IsAuthorizedStream struct {
}
func (x *drpcAuthorizer_IsAuthorizedStream) SendAndClose(m *IsAuthorizedResponse) error {
- if err := x.MsgSend(m, drpcEncoding_File_enterprise_x_aibridged_proto_aibridged_proto{}); err != nil {
+ if err := x.MsgSend(m, drpcEncoding_File_enterprise_aibridged_proto_aibridged_proto{}); err != nil {
return err
}
return x.CloseSend()
diff --git a/enterprise/x/aibridged/request.go b/enterprise/aibridged/request.go
similarity index 100%
rename from enterprise/x/aibridged/request.go
rename to enterprise/aibridged/request.go
diff --git a/enterprise/x/aibridged/server.go b/enterprise/aibridged/server.go
similarity index 68%
rename from enterprise/x/aibridged/server.go
rename to enterprise/aibridged/server.go
index 713ea2a0cd126..052c94dad4a9e 100644
--- a/enterprise/x/aibridged/server.go
+++ b/enterprise/aibridged/server.go
@@ -1,6 +1,6 @@
package aibridged
-import "github.com/coder/coder/v2/enterprise/x/aibridged/proto"
+import "github.com/coder/coder/v2/enterprise/aibridged/proto"
type DRPCServer interface {
proto.DRPCRecorderServer
diff --git a/enterprise/x/aibridged/translator.go b/enterprise/aibridged/translator.go
similarity index 98%
rename from enterprise/x/aibridged/translator.go
rename to enterprise/aibridged/translator.go
index bfc39d834ad2c..f36185715a745 100644
--- a/enterprise/x/aibridged/translator.go
+++ b/enterprise/aibridged/translator.go
@@ -11,7 +11,7 @@ import (
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/coder/coder/v2/coderd/util/ptr"
- "github.com/coder/coder/v2/enterprise/x/aibridged/proto"
+ "github.com/coder/coder/v2/enterprise/aibridged/proto"
"github.com/coder/aibridge"
)
diff --git a/enterprise/x/aibridged/utils_test.go b/enterprise/aibridged/utils_test.go
similarity index 100%
rename from enterprise/x/aibridged/utils_test.go
rename to enterprise/aibridged/utils_test.go
diff --git a/enterprise/x/aibridgedserver/aibridgedserver.go b/enterprise/aibridgedserver/aibridgedserver.go
similarity index 99%
rename from enterprise/x/aibridgedserver/aibridgedserver.go
rename to enterprise/aibridgedserver/aibridgedserver.go
index 2c5e3ff71c072..6adf7b793c1d2 100644
--- a/enterprise/x/aibridgedserver/aibridgedserver.go
+++ b/enterprise/aibridgedserver/aibridgedserver.go
@@ -24,8 +24,8 @@ import (
"github.com/coder/coder/v2/coderd/httpmw"
codermcp "github.com/coder/coder/v2/coderd/mcp"
"github.com/coder/coder/v2/codersdk"
- "github.com/coder/coder/v2/enterprise/x/aibridged"
- "github.com/coder/coder/v2/enterprise/x/aibridged/proto"
+ "github.com/coder/coder/v2/enterprise/aibridged"
+ "github.com/coder/coder/v2/enterprise/aibridged/proto"
)
var (
diff --git a/enterprise/x/aibridgedserver/aibridgedserver_internal_test.go b/enterprise/aibridgedserver/aibridgedserver_internal_test.go
similarity index 100%
rename from enterprise/x/aibridgedserver/aibridgedserver_internal_test.go
rename to enterprise/aibridgedserver/aibridgedserver_internal_test.go
diff --git a/enterprise/x/aibridgedserver/aibridgedserver_test.go b/enterprise/aibridgedserver/aibridgedserver_test.go
similarity index 99%
rename from enterprise/x/aibridgedserver/aibridgedserver_test.go
rename to enterprise/aibridgedserver/aibridgedserver_test.go
index 4f9f892bc886a..27598c79857f1 100644
--- a/enterprise/x/aibridgedserver/aibridgedserver_test.go
+++ b/enterprise/aibridgedserver/aibridgedserver_test.go
@@ -28,9 +28,9 @@ import (
codermcp "github.com/coder/coder/v2/coderd/mcp"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/cryptorand"
- "github.com/coder/coder/v2/enterprise/x/aibridged"
- "github.com/coder/coder/v2/enterprise/x/aibridged/proto"
- "github.com/coder/coder/v2/enterprise/x/aibridgedserver"
+ "github.com/coder/coder/v2/enterprise/aibridged"
+ "github.com/coder/coder/v2/enterprise/aibridged/proto"
+ "github.com/coder/coder/v2/enterprise/aibridgedserver"
"github.com/coder/coder/v2/testutil"
)
diff --git a/enterprise/cli/exp_aibridge.go b/enterprise/cli/aibridge.go
similarity index 97%
rename from enterprise/cli/exp_aibridge.go
rename to enterprise/cli/aibridge.go
index 722f7bf239223..90953b6aa2bf2 100644
--- a/enterprise/cli/exp_aibridge.go
+++ b/enterprise/cli/aibridge.go
@@ -134,8 +134,7 @@ func (r *RootCmd) aibridgeInterceptionsList() *serpent.Command {
return xerrors.Errorf("limit value must be between 1 and %d", maxInterceptionsLimit)
}
- expCli := codersdk.NewExperimentalClient(client)
- resp, err := expCli.AIBridgeListInterceptions(inv.Context(), codersdk.AIBridgeListInterceptionsFilter{
+ resp, err := client.AIBridgeListInterceptions(inv.Context(), codersdk.AIBridgeListInterceptionsFilter{
Pagination: codersdk.Pagination{
AfterID: afterID,
// #nosec G115 - Checked above.
diff --git a/enterprise/cli/exp_aibridge_test.go b/enterprise/cli/aibridge_test.go
similarity index 96%
rename from enterprise/cli/exp_aibridge_test.go
rename to enterprise/cli/aibridge_test.go
index 466d6b3df8246..a5b48a14e1c38 100644
--- a/enterprise/cli/exp_aibridge_test.go
+++ b/enterprise/cli/aibridge_test.go
@@ -27,7 +27,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
t.Parallel()
dv := coderdtest.DeploymentValues(t)
- dv.Experiments = []string{string(codersdk.ExperimentAIBridge)}
client, db, owner := coderdenttest.NewWithDatabase(t, &coderdenttest.Options{
Options: &coderdtest.Options{
DeploymentValues: dv,
@@ -55,7 +54,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
}, nil)
args := []string{
- "exp",
"aibridge",
"interceptions",
"list",
@@ -78,7 +76,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
t.Parallel()
dv := coderdtest.DeploymentValues(t)
- dv.Experiments = []string{string(codersdk.ExperimentAIBridge)}
client, db, owner := coderdenttest.NewWithDatabase(t, &coderdenttest.Options{
Options: &coderdtest.Options{
DeploymentValues: dv,
@@ -137,7 +134,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
}, nil)
args := []string{
- "exp",
"aibridge",
"interceptions",
"list",
@@ -164,7 +160,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
t.Parallel()
dv := coderdtest.DeploymentValues(t)
- dv.Experiments = []string{string(codersdk.ExperimentAIBridge)}
client, db, owner := coderdenttest.NewWithDatabase(t, &coderdenttest.Options{
Options: &coderdtest.Options{
DeploymentValues: dv,
@@ -192,7 +187,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
}, nil)
args := []string{
- "exp",
"aibridge",
"interceptions",
"list",
diff --git a/enterprise/cli/aibridged.go b/enterprise/cli/aibridged.go
index 17bb5ebe681fa..b2dc3d7725b93 100644
--- a/enterprise/cli/aibridged.go
+++ b/enterprise/cli/aibridged.go
@@ -9,8 +9,8 @@ import (
"github.com/coder/aibridge"
"github.com/coder/coder/v2/codersdk"
+ "github.com/coder/coder/v2/enterprise/aibridged"
"github.com/coder/coder/v2/enterprise/coderd"
- "github.com/coder/coder/v2/enterprise/x/aibridged"
)
func newAIBridgeDaemon(coderAPI *coderd.API) (*aibridged.Server, error) {
diff --git a/enterprise/cli/root.go b/enterprise/cli/root.go
index 3cec11970369e..78858ef48da7b 100644
--- a/enterprise/cli/root.go
+++ b/enterprise/cli/root.go
@@ -25,13 +25,12 @@ func (r *RootCmd) enterpriseOnly() []*serpent.Command {
r.prebuilds(),
r.provisionerd(),
r.externalWorkspaces(),
+ r.aibridge(),
}
}
-func (r *RootCmd) enterpriseExperimental() []*serpent.Command {
- return []*serpent.Command{
- r.aibridge(),
- }
+func (*RootCmd) enterpriseExperimental() []*serpent.Command {
+ return []*serpent.Command{}
}
func (r *RootCmd) EnterpriseSubcommands() []*serpent.Command {
diff --git a/enterprise/cli/server.go b/enterprise/cli/server.go
index ea9f2d3e93825..bc77bc54ba522 100644
--- a/enterprise/cli/server.go
+++ b/enterprise/cli/server.go
@@ -7,7 +7,6 @@ import (
"database/sql"
"encoding/base64"
"errors"
- "fmt"
"io"
"net/url"
@@ -16,8 +15,8 @@ import (
"tailscale.com/types/key"
"github.com/coder/coder/v2/coderd/database"
- "github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/cryptorand"
+ "github.com/coder/coder/v2/enterprise/aibridged"
"github.com/coder/coder/v2/enterprise/audit"
"github.com/coder/coder/v2/enterprise/audit/backends"
"github.com/coder/coder/v2/enterprise/coderd"
@@ -25,7 +24,6 @@ import (
"github.com/coder/coder/v2/enterprise/coderd/usage"
"github.com/coder/coder/v2/enterprise/dbcrypt"
"github.com/coder/coder/v2/enterprise/trialer"
- "github.com/coder/coder/v2/enterprise/x/aibridged"
"github.com/coder/coder/v2/tailnet"
"github.com/coder/quartz"
"github.com/coder/serpent"
@@ -146,8 +144,6 @@ func (r *RootCmd) Server(_ func()) *serpent.Command {
}
closers.Add(publisher)
- experiments := agplcoderd.ReadExperiments(options.Logger, options.DeploymentValues.Experiments.Value())
-
// In-memory aibridge daemon.
// TODO(@deansheather): the lifecycle of the aibridged server is
// probably better managed by the enterprise API type itself. Managing
@@ -155,26 +151,18 @@ func (r *RootCmd) Server(_ func()) *serpent.Command {
// is not entitled to the feature.
var aibridgeDaemon *aibridged.Server
if options.DeploymentValues.AI.BridgeConfig.Enabled {
- if experiments.Enabled(codersdk.ExperimentAIBridge) {
- aibridgeDaemon, err = newAIBridgeDaemon(api)
- if err != nil {
- return nil, nil, xerrors.Errorf("create aibridged: %w", err)
- }
+ aibridgeDaemon, err = newAIBridgeDaemon(api)
+ if err != nil {
+ return nil, nil, xerrors.Errorf("create aibridged: %w", err)
+ }
- api.RegisterInMemoryAIBridgedHTTPHandler(aibridgeDaemon)
+ api.RegisterInMemoryAIBridgedHTTPHandler(aibridgeDaemon)
- // When running as an in-memory daemon, the HTTP handler is wired into the
- // coderd API and therefore is subject to its context. Calling Close() on
- // aibridged will NOT affect in-flight requests but those will be closed once
- // the API server is itself shutdown.
- closers.Add(aibridgeDaemon)
- } else {
- api.Logger.Warn(ctx, fmt.Sprintf("CODER_AIBRIDGE_ENABLED=true but experiment %q not enabled", codersdk.ExperimentAIBridge))
- }
- } else {
- if experiments.Enabled(codersdk.ExperimentAIBridge) {
- api.Logger.Warn(ctx, "aibridge experiment enabled but CODER_AIBRIDGE_ENABLED=false")
- }
+ // When running as an in-memory daemon, the HTTP handler is wired into the
+ // coderd API and therefore is subject to its context. Calling Close() on
+ // aibridged will NOT affect in-flight requests but those will be closed once
+ // the API server is itself shutdown.
+ closers.Add(aibridgeDaemon)
}
return api.AGPL, closers, nil
diff --git a/enterprise/cli/testdata/coder_--help.golden b/enterprise/cli/testdata/coder_--help.golden
index ddb44f78ae524..8424ccac923a2 100644
--- a/enterprise/cli/testdata/coder_--help.golden
+++ b/enterprise/cli/testdata/coder_--help.golden
@@ -14,6 +14,7 @@ USAGE:
$ coder templates init
SUBCOMMANDS:
+ aibridge Manage AIBridge.
external-workspaces Create or manage external workspaces
features List Enterprise features
groups Manage groups
diff --git a/enterprise/cli/testdata/coder_aibridge_--help.golden b/enterprise/cli/testdata/coder_aibridge_--help.golden
new file mode 100644
index 0000000000000..d005ae429ad50
--- /dev/null
+++ b/enterprise/cli/testdata/coder_aibridge_--help.golden
@@ -0,0 +1,12 @@
+coder v0.0.0-devel
+
+USAGE:
+ coder aibridge
+
+ Manage AIBridge.
+
+SUBCOMMANDS:
+ interceptions Manage AIBridge interceptions.
+
+———
+Run `coder --help` for a list of global options.
diff --git a/enterprise/cli/testdata/coder_aibridge_interceptions_--help.golden b/enterprise/cli/testdata/coder_aibridge_interceptions_--help.golden
new file mode 100644
index 0000000000000..1f3b3af5ad3d3
--- /dev/null
+++ b/enterprise/cli/testdata/coder_aibridge_interceptions_--help.golden
@@ -0,0 +1,12 @@
+coder v0.0.0-devel
+
+USAGE:
+ coder aibridge interceptions
+
+ Manage AIBridge interceptions.
+
+SUBCOMMANDS:
+ list List AIBridge interceptions as JSON.
+
+———
+Run `coder --help` for a list of global options.
diff --git a/enterprise/cli/testdata/coder_aibridge_interceptions_list_--help.golden b/enterprise/cli/testdata/coder_aibridge_interceptions_list_--help.golden
new file mode 100644
index 0000000000000..c98fd0019a45a
--- /dev/null
+++ b/enterprise/cli/testdata/coder_aibridge_interceptions_list_--help.golden
@@ -0,0 +1,37 @@
+coder v0.0.0-devel
+
+USAGE:
+ coder aibridge interceptions list [flags]
+
+ List AIBridge interceptions as JSON.
+
+OPTIONS:
+ --after-id string
+ The ID of the last result on the previous page to use as a pagination
+ cursor.
+
+ --initiator string
+ Only return interceptions initiated by this user. Accepts a user ID,
+ username, or "me".
+
+ --limit int (default: 100)
+ The limit of results to return. Must be between 1 and 1000.
+
+ --model string
+ Only return interceptions from this model.
+
+ --provider string
+ Only return interceptions from this provider.
+
+ --started-after string
+ Only return interceptions started after this time. Must be before
+ 'started-before' if set. Accepts a time in the RFC 3339 format, e.g.
+ "====[timestamp]=====07:00".
+
+ --started-before string
+ Only return interceptions started before this time. Must be after
+ 'started-after' if set. Accepts a time in the RFC 3339 format, e.g.
+ "====[timestamp]=====07:00".
+
+———
+Run `coder --help` for a list of global options.
diff --git a/enterprise/cli/testdata/coder_server_--help.golden b/enterprise/cli/testdata/coder_server_--help.golden
index 162d4214ccc6a..492306c55882d 100644
--- a/enterprise/cli/testdata/coder_server_--help.golden
+++ b/enterprise/cli/testdata/coder_server_--help.golden
@@ -81,6 +81,41 @@ OPTIONS:
Periodically check for new releases of Coder and inform the owner. The
check is performed once per day.
+AIBRIDGE OPTIONS:
+ --aibridge-anthropic-base-url string, $CODER_AIBRIDGE_ANTHROPIC_BASE_URL (default: https://api.anthropic.com/)
+ The base URL of the Anthropic API.
+
+ --aibridge-anthropic-key string, $CODER_AIBRIDGE_ANTHROPIC_KEY
+ The key to authenticate against the Anthropic API.
+
+ --aibridge-bedrock-access-key string, $CODER_AIBRIDGE_BEDROCK_ACCESS_KEY
+ The access key to authenticate against the AWS Bedrock API.
+
+ --aibridge-bedrock-access-key-secret string, $CODER_AIBRIDGE_BEDROCK_ACCESS_KEY_SECRET
+ The access key secret to use with the access key to authenticate
+ against the AWS Bedrock API.
+
+ --aibridge-bedrock-model string, $CODER_AIBRIDGE_BEDROCK_MODEL (default: global.anthropic.claude-sonnet-4-5-20250929-v1:0)
+ The model to use when making requests to the AWS Bedrock API.
+
+ --aibridge-bedrock-region string, $CODER_AIBRIDGE_BEDROCK_REGION
+ The AWS Bedrock API region.
+
+ --aibridge-bedrock-small-fastmodel string, $CODER_AIBRIDGE_BEDROCK_SMALL_FAST_MODEL (default: global.anthropic.claude-haiku-4-5-20251001-v1:0)
+ The small fast model to use when making requests to the AWS Bedrock
+ API. Claude Code uses Haiku-class models to perform background tasks.
+ See
+ https://docs.claude.com/en/docs/claude-code/settings#environment-variables.
+
+ --aibridge-enabled bool, $CODER_AIBRIDGE_ENABLED (default: false)
+ Whether to start an in-memory aibridged instance.
+
+ --aibridge-openai-base-url string, $CODER_AIBRIDGE_OPENAI_BASE_URL (default: https://api.openai.com/v1/)
+ The base URL of the OpenAI API.
+
+ --aibridge-openai-key string, $CODER_AIBRIDGE_OPENAI_KEY
+ The key to authenticate against the OpenAI API.
+
CLIENT OPTIONS:
These options change the behavior of how clients interact with the Coder.
Clients include the Coder CLI, Coder Desktop, IDE extensions, and the web UI.
diff --git a/enterprise/coderd/aibridge.go b/enterprise/coderd/aibridge.go
index dab93d8992a79..bdd2a99166910 100644
--- a/enterprise/coderd/aibridge.go
+++ b/enterprise/coderd/aibridge.go
@@ -36,7 +36,7 @@ const (
// @Param after_id query string false "Cursor pagination after ID (cannot be used with offset)"
// @Param offset query int false "Offset pagination (cannot be used with after_id)"
// @Success 200 {object} codersdk.AIBridgeListInterceptionsResponse
-// @Router /api/experimental/aibridge/interceptions [get]
+// @Router /aibridge/interceptions [get]
func (api *API) aiBridgeListInterceptions(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
apiKey := httpmw.APIKey(r)
diff --git a/enterprise/coderd/aibridge_test.go b/enterprise/coderd/aibridge_test.go
index abaf82dbe85f8..17e5df56fb65d 100644
--- a/enterprise/coderd/aibridge_test.go
+++ b/enterprise/coderd/aibridge_test.go
@@ -27,7 +27,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
t.Parallel()
dv := coderdtest.DeploymentValues(t)
- dv.Experiments = []string{string(codersdk.ExperimentAIBridge)}
client, _ := coderdenttest.New(t, &coderdenttest.Options{
Options: &coderdtest.Options{
DeploymentValues: dv,
@@ -37,10 +36,10 @@ func TestAIBridgeListInterceptions(t *testing.T) {
Features: license.Features{},
},
})
- experimentalClient := codersdk.NewExperimentalClient(client)
ctx := testutil.Context(t, testutil.WaitLong)
- _, err := experimentalClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{})
+ //nolint:gocritic // Owner role is irrelevant here.
+ _, err := client.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{})
var sdkErr *codersdk.Error
require.ErrorAs(t, err, &sdkErr)
require.Equal(t, http.StatusForbidden, sdkErr.StatusCode())
@@ -50,7 +49,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
t.Run("EmptyDB", func(t *testing.T) {
t.Parallel()
dv := coderdtest.DeploymentValues(t)
- dv.Experiments = []string{string(codersdk.ExperimentAIBridge)}
client, _ := coderdenttest.New(t, &coderdenttest.Options{
Options: &coderdtest.Options{
DeploymentValues: dv,
@@ -61,9 +59,9 @@ func TestAIBridgeListInterceptions(t *testing.T) {
},
},
})
- experimentalClient := codersdk.NewExperimentalClient(client)
ctx := testutil.Context(t, testutil.WaitLong)
- res, err := experimentalClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{})
+ //nolint:gocritic // Owner role is irrelevant here.
+ res, err := client.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{})
require.NoError(t, err)
require.Empty(t, res.Results)
})
@@ -71,7 +69,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
t.Run("OK", func(t *testing.T) {
t.Parallel()
dv := coderdtest.DeploymentValues(t)
- dv.Experiments = []string{string(codersdk.ExperimentAIBridge)}
client, db, firstUser := coderdenttest.NewWithDatabase(t, &coderdenttest.Options{
Options: &coderdtest.Options{
DeploymentValues: dv,
@@ -82,7 +79,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
},
},
})
- experimentalClient := codersdk.NewExperimentalClient(client)
ctx := testutil.Context(t, testutil.WaitLong)
user1, err := client.User(ctx, codersdk.Me)
@@ -143,7 +139,7 @@ func TestAIBridgeListInterceptions(t *testing.T) {
i1SDK := db2sdk.AIBridgeInterception(i1, user1Visible, []database.AIBridgeTokenUsage{i1tok2, i1tok1}, []database.AIBridgeUserPrompt{i1up2, i1up1}, []database.AIBridgeToolUsage{i1tool2, i1tool1})
i2SDK := db2sdk.AIBridgeInterception(i2, user2Visible, nil, nil, nil)
- res, err := experimentalClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{})
+ res, err := client.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{})
require.NoError(t, err)
require.Len(t, res.Results, 2)
require.Equal(t, i2SDK.ID, res.Results[0].ID)
@@ -183,7 +179,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
t.Parallel()
dv := coderdtest.DeploymentValues(t)
- dv.Experiments = []string{string(codersdk.ExperimentAIBridge)}
client, db, firstUser := coderdenttest.NewWithDatabase(t, &coderdenttest.Options{
Options: &coderdtest.Options{
DeploymentValues: dv,
@@ -194,7 +189,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
},
},
})
- experimentalClient := codersdk.NewExperimentalClient(client)
ctx := testutil.Context(t, testutil.WaitLong)
allInterceptionIDs := make([]uuid.UUID, 0, 20)
@@ -225,7 +219,7 @@ func TestAIBridgeListInterceptions(t *testing.T) {
}
// Try to fetch with an invalid limit.
- res, err := experimentalClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{
+ res, err := client.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{
Pagination: codersdk.Pagination{
Limit: 1001,
},
@@ -236,7 +230,7 @@ func TestAIBridgeListInterceptions(t *testing.T) {
require.Empty(t, res.Results)
// Try to fetch with both after_id and offset pagination.
- res, err = experimentalClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{
+ res, err = client.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{
Pagination: codersdk.Pagination{
AfterID: allInterceptionIDs[0],
Offset: 1,
@@ -269,7 +263,7 @@ func TestAIBridgeListInterceptions(t *testing.T) {
} else {
pagination.Offset = len(interceptionIDs)
}
- res, err := experimentalClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{
+ res, err := client.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{
Pagination: pagination,
})
require.NoError(t, err)
@@ -299,7 +293,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
t.Run("Authorized", func(t *testing.T) {
t.Parallel()
dv := coderdtest.DeploymentValues(t)
- dv.Experiments = []string{string(codersdk.ExperimentAIBridge)}
adminClient, db, firstUser := coderdenttest.NewWithDatabase(t, &coderdenttest.Options{
Options: &coderdtest.Options{
DeploymentValues: dv,
@@ -310,11 +303,9 @@ func TestAIBridgeListInterceptions(t *testing.T) {
},
},
})
- adminExperimentalClient := codersdk.NewExperimentalClient(adminClient)
ctx := testutil.Context(t, testutil.WaitLong)
secondUserClient, secondUser := coderdtest.CreateAnotherUser(t, adminClient, firstUser.OrganizationID)
- secondUserExperimentalClient := codersdk.NewExperimentalClient(secondUserClient)
now := dbtime.Now()
i1 := dbgen.AIBridgeInterception(t, db, database.InsertAIBridgeInterceptionParams{
@@ -327,7 +318,7 @@ func TestAIBridgeListInterceptions(t *testing.T) {
}, &now)
// Admin can see all interceptions.
- res, err := adminExperimentalClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{})
+ res, err := adminClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{})
require.NoError(t, err)
require.EqualValues(t, 2, res.Count)
require.Len(t, res.Results, 2)
@@ -335,7 +326,7 @@ func TestAIBridgeListInterceptions(t *testing.T) {
require.Equal(t, i2.ID, res.Results[1].ID)
// Second user can only see their own interceptions.
- res, err = secondUserExperimentalClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{})
+ res, err = secondUserClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{})
require.NoError(t, err)
require.EqualValues(t, 1, res.Count)
require.Len(t, res.Results, 1)
@@ -345,7 +336,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
t.Run("Filter", func(t *testing.T) {
t.Parallel()
dv := coderdtest.DeploymentValues(t)
- dv.Experiments = []string{string(codersdk.ExperimentAIBridge)}
client, db, firstUser := coderdenttest.NewWithDatabase(t, &coderdenttest.Options{
Options: &coderdtest.Options{
DeploymentValues: dv,
@@ -356,7 +346,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
},
},
})
- experimentalClient := codersdk.NewExperimentalClient(client)
ctx := testutil.Context(t, testutil.WaitLong)
user1, err := client.User(ctx, codersdk.Me)
@@ -506,7 +495,7 @@ func TestAIBridgeListInterceptions(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
- res, err := experimentalClient.AIBridgeListInterceptions(ctx, tc.filter)
+ res, err := client.AIBridgeListInterceptions(ctx, tc.filter)
require.NoError(t, err)
require.EqualValues(t, len(tc.want), res.Count)
// We just compare UUID strings for the sake of this test.
@@ -526,7 +515,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
t.Run("FilterErrors", func(t *testing.T) {
t.Parallel()
dv := coderdtest.DeploymentValues(t)
- dv.Experiments = []string{string(codersdk.ExperimentAIBridge)}
client, _ := coderdenttest.New(t, &coderdenttest.Options{
Options: &coderdtest.Options{
DeploymentValues: dv,
@@ -537,7 +525,6 @@ func TestAIBridgeListInterceptions(t *testing.T) {
},
},
})
- experimentalClient := codersdk.NewExperimentalClient(client)
// No need to insert any test data, we're just testing the filter
// errors.
@@ -594,7 +581,7 @@ func TestAIBridgeListInterceptions(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitLong)
- res, err := experimentalClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{
+ res, err := client.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{
FilterQuery: tc.q,
})
var sdkErr *codersdk.Error
diff --git a/enterprise/coderd/aibridged.go b/enterprise/coderd/aibridged.go
index bf991103b1f52..285575df33862 100644
--- a/enterprise/coderd/aibridged.go
+++ b/enterprise/coderd/aibridged.go
@@ -14,9 +14,9 @@ import (
"github.com/coder/coder/v2/coderd/tracing"
"github.com/coder/coder/v2/codersdk/drpcsdk"
- "github.com/coder/coder/v2/enterprise/x/aibridged"
- aibridgedproto "github.com/coder/coder/v2/enterprise/x/aibridged/proto"
- "github.com/coder/coder/v2/enterprise/x/aibridgedserver"
+ "github.com/coder/coder/v2/enterprise/aibridged"
+ aibridgedproto "github.com/coder/coder/v2/enterprise/aibridged/proto"
+ "github.com/coder/coder/v2/enterprise/aibridgedserver"
)
// RegisterInMemoryAIBridgedHTTPHandler mounts [aibridged.Server]'s HTTP router onto
diff --git a/enterprise/coderd/coderd.go b/enterprise/coderd/coderd.go
index 7666e8f957fc2..a4adb0479b96b 100644
--- a/enterprise/coderd/coderd.go
+++ b/enterprise/coderd/coderd.go
@@ -226,12 +226,9 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
return api.refreshEntitlements(ctx)
}
- api.AGPL.ExperimentalHandler.Group(func(r chi.Router) {
+ api.AGPL.APIHandler.Group(func(r chi.Router) {
r.Route("/aibridge", func(r chi.Router) {
- r.Use(
- api.RequireFeatureMW(codersdk.FeatureAIBridge),
- httpmw.RequireExperimentWithDevBypass(api.AGPL.Experiments, codersdk.ExperimentAIBridge),
- )
+ r.Use(api.RequireFeatureMW(codersdk.FeatureAIBridge))
r.Group(func(r chi.Router) {
r.Use(apiKeyMiddleware)
r.Get("/interceptions", api.aiBridgeListInterceptions)
@@ -246,7 +243,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
})
return
}
- http.StripPrefix("/api/experimental/aibridge", api.aibridgedHandler).ServeHTTP(rw, r)
+ http.StripPrefix("/api/v2/aibridge", api.aibridgedHandler).ServeHTTP(rw, r)
})
})
})
diff --git a/enterprise/coderd/prebuilds/membership.go b/enterprise/coderd/prebuilds/membership.go
index f843d33f7f106..9436f68737d4a 100644
--- a/enterprise/coderd/prebuilds/membership.go
+++ b/enterprise/coderd/prebuilds/membership.go
@@ -2,12 +2,13 @@ package prebuilds
import (
"context"
- "database/sql"
"errors"
"github.com/google/uuid"
"golang.org/x/xerrors"
+ "cdr.dev/slog"
+
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/quartz"
)
@@ -21,114 +22,117 @@ const (
// organizations for which prebuilt workspaces are requested. This is necessary because our data model requires that such
// prebuilt workspaces belong to a member of the organization of their eventual claimant.
type StoreMembershipReconciler struct {
- store database.Store
- clock quartz.Clock
+ store database.Store
+ clock quartz.Clock
+ logger slog.Logger
}
-func NewStoreMembershipReconciler(store database.Store, clock quartz.Clock) StoreMembershipReconciler {
+func NewStoreMembershipReconciler(store database.Store, clock quartz.Clock, logger slog.Logger) StoreMembershipReconciler {
return StoreMembershipReconciler{
- store: store,
- clock: clock,
+ store: store,
+ clock: clock,
+ logger: logger,
}
}
-// ReconcileAll compares the current organization and group memberships of a user to the memberships required
-// in order to create prebuilt workspaces. If the user in question is not yet a member of an organization that
-// needs prebuilt workspaces, ReconcileAll will create the membership required.
+// ReconcileAll ensures the prebuilds system user has the necessary memberships to create prebuilt workspaces.
+// For each organization with prebuilds configured, it ensures:
+// * The user is a member of the organization
+// * A group exists with quota 0
+// * The user is a member of that group
//
-// To facilitate quota management, ReconcileAll will ensure:
-// * the existence of a group (defined by PrebuiltWorkspacesGroupName) in each organization that needs prebuilt workspaces
-// * that the prebuilds system user belongs to the group in each organization that needs prebuilt workspaces
-// * that the group has a quota of 0 by default, which users can adjust based on their needs.
+// Unique constraint violations are safely ignored (concurrent creation).
//
// ReconcileAll does not have an opinion on transaction or lock management. These responsibilities are left to the caller.
-func (s StoreMembershipReconciler) ReconcileAll(ctx context.Context, userID uuid.UUID, presets []database.GetTemplatePresetsWithPrebuildsRow) error {
- organizationMemberships, err := s.store.GetOrganizationsByUserID(ctx, database.GetOrganizationsByUserIDParams{
- UserID: userID,
- Deleted: sql.NullBool{
- Bool: false,
- Valid: true,
- },
+func (s StoreMembershipReconciler) ReconcileAll(ctx context.Context, userID uuid.UUID, groupName string) error {
+ orgStatuses, err := s.store.GetOrganizationsWithPrebuildStatus(ctx, database.GetOrganizationsWithPrebuildStatusParams{
+ UserID: userID,
+ GroupName: groupName,
})
if err != nil {
- return xerrors.Errorf("determine prebuild organization membership: %w", err)
- }
-
- orgMemberships := make(map[uuid.UUID]struct{}, 0)
- defaultOrg, err := s.store.GetDefaultOrganization(ctx)
- if err != nil {
- return xerrors.Errorf("get default organization: %w", err)
- }
- orgMemberships[defaultOrg.ID] = struct{}{}
- for _, o := range organizationMemberships {
- orgMemberships[o.ID] = struct{}{}
+ return xerrors.Errorf("get organizations with prebuild status: %w", err)
}
var membershipInsertionErrors error
- for _, preset := range presets {
- _, alreadyOrgMember := orgMemberships[preset.OrganizationID]
- if !alreadyOrgMember {
- // Add the organization to our list of memberships regardless of potential failure below
- // to avoid a retry that will probably be doomed anyway.
- orgMemberships[preset.OrganizationID] = struct{}{}
+ for _, orgStatus := range orgStatuses {
+ s.logger.Debug(ctx, "organization prebuild status",
+ slog.F("organization_id", orgStatus.OrganizationID),
+ slog.F("organization_name", orgStatus.OrganizationName),
+ slog.F("has_prebuild_user", orgStatus.HasPrebuildUser),
+ slog.F("has_prebuild_group", orgStatus.PrebuildsGroupID.Valid),
+ slog.F("has_prebuild_user_in_group", orgStatus.HasPrebuildUserInGroup))
- // Insert the missing membership
+ // Add user to org if needed
+ if !orgStatus.HasPrebuildUser {
_, err = s.store.InsertOrganizationMember(ctx, database.InsertOrganizationMemberParams{
- OrganizationID: preset.OrganizationID,
+ OrganizationID: orgStatus.OrganizationID,
UserID: userID,
CreatedAt: s.clock.Now(),
UpdatedAt: s.clock.Now(),
Roles: []string{},
})
- if err != nil {
- membershipInsertionErrors = errors.Join(membershipInsertionErrors, xerrors.Errorf("insert membership for prebuilt workspaces: %w", err))
+ // Unique violation means organization membership was created after status check, safe to ignore.
+ if err != nil && !database.IsUniqueViolation(err) {
+ membershipInsertionErrors = errors.Join(membershipInsertionErrors, err)
continue
}
- }
-
- // determine whether the org already has a prebuilds group
- prebuildsGroupExists := true
- prebuildsGroup, err := s.store.GetGroupByOrgAndName(ctx, database.GetGroupByOrgAndNameParams{
- OrganizationID: preset.OrganizationID,
- Name: PrebuiltWorkspacesGroupName,
- })
- if err != nil {
- if !xerrors.Is(err, sql.ErrNoRows) {
- membershipInsertionErrors = errors.Join(membershipInsertionErrors, xerrors.Errorf("get prebuilds group: %w", err))
- continue
+ if err == nil {
+ s.logger.Info(ctx, "added prebuilds user to organization",
+ slog.F("organization_id", orgStatus.OrganizationID),
+ slog.F("organization_name", orgStatus.OrganizationName),
+ slog.F("prebuilds_user", userID.String()))
}
- prebuildsGroupExists = false
}
- // if the prebuilds group does not exist, create it
- if !prebuildsGroupExists {
- // create a "prebuilds" group in the organization and add the system user to it
- // this group will have a quota of 0 by default, which users can adjust based on their needs
- prebuildsGroup, err = s.store.InsertGroup(ctx, database.InsertGroupParams{
+ // Create group if it doesn't exist
+ var groupID uuid.UUID
+ if !orgStatus.PrebuildsGroupID.Valid {
+ // Group doesn't exist, create it
+ group, err := s.store.InsertGroup(ctx, database.InsertGroupParams{
ID: uuid.New(),
Name: PrebuiltWorkspacesGroupName,
DisplayName: PrebuiltWorkspacesGroupDisplayName,
- OrganizationID: preset.OrganizationID,
+ OrganizationID: orgStatus.OrganizationID,
AvatarURL: "",
- QuotaAllowance: 0, // Default quota of 0, users should set this based on their needs
+ QuotaAllowance: 0,
})
- if err != nil {
- membershipInsertionErrors = errors.Join(membershipInsertionErrors, xerrors.Errorf("create prebuilds group: %w", err))
+ // Unique violation means group was created after status check, safe to ignore.
+ if err != nil && !database.IsUniqueViolation(err) {
+ membershipInsertionErrors = errors.Join(membershipInsertionErrors, err)
continue
}
+ if err == nil {
+ s.logger.Info(ctx, "created prebuilds group in organization",
+ slog.F("organization_id", orgStatus.OrganizationID),
+ slog.F("organization_name", orgStatus.OrganizationName),
+ slog.F("prebuilds_group", group.ID.String()))
+ }
+ groupID = group.ID
+ } else {
+ // Group exists
+ groupID = orgStatus.PrebuildsGroupID.UUID
}
- // add the system user to the prebuilds group
- err = s.store.InsertGroupMember(ctx, database.InsertGroupMemberParams{
- GroupID: prebuildsGroup.ID,
- UserID: userID,
- })
- if err != nil {
- // ignore unique violation errors as the user might already be in the group
- if !database.IsUniqueViolation(err) {
- membershipInsertionErrors = errors.Join(membershipInsertionErrors, xerrors.Errorf("add system user to prebuilds group: %w", err))
+ // Add user to group if needed
+ if !orgStatus.HasPrebuildUserInGroup {
+ err = s.store.InsertGroupMember(ctx, database.InsertGroupMemberParams{
+ GroupID: groupID,
+ UserID: userID,
+ })
+ // Unique violation means group membership was created after status check, safe to ignore.
+ if err != nil && !database.IsUniqueViolation(err) {
+ membershipInsertionErrors = errors.Join(membershipInsertionErrors, err)
+ continue
+ }
+ if err == nil {
+ s.logger.Info(ctx, "added prebuilds user to prebuilds group",
+ slog.F("organization_id", orgStatus.OrganizationID),
+ slog.F("organization_name", orgStatus.OrganizationName),
+ slog.F("prebuilds_user", userID.String()),
+ slog.F("prebuilds_group", groupID.String()))
}
}
}
+
return membershipInsertionErrors
}
diff --git a/enterprise/coderd/prebuilds/membership_test.go b/enterprise/coderd/prebuilds/membership_test.go
index 55d6557b12495..fe4ec26259889 100644
--- a/enterprise/coderd/prebuilds/membership_test.go
+++ b/enterprise/coderd/prebuilds/membership_test.go
@@ -7,16 +7,17 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/require"
- "tailscale.com/types/ptr"
- "github.com/coder/quartz"
+ "cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbauthz"
+ "github.com/coder/coder/v2/coderd/database/dbfake"
"github.com/coder/coder/v2/coderd/database/dbgen"
"github.com/coder/coder/v2/enterprise/coderd/prebuilds"
"github.com/coder/coder/v2/testutil"
+ "github.com/coder/quartz"
)
// TestReconcileAll verifies that StoreMembershipReconciler correctly updates membership
@@ -26,169 +27,178 @@ func TestReconcileAll(t *testing.T) {
clock := quartz.NewMock(t)
- // Helper to build a minimal Preset row belonging to a given org.
- newPresetRow := func(orgID uuid.UUID) database.GetTemplatePresetsWithPrebuildsRow {
- return database.GetTemplatePresetsWithPrebuildsRow{
- ID: uuid.New(),
- OrganizationID: orgID,
- }
- }
-
tests := []struct {
name string
- includePreset []bool
+ includePreset bool
preExistingOrgMembership []bool
preExistingGroup []bool
preExistingGroupMembership []bool
// Expected outcomes
- expectOrgMembershipExists *bool
- expectGroupExists *bool
- expectUserInGroup *bool
+ expectOrgMembershipExists bool
+ expectGroupExists bool
+ expectUserInGroup bool
}{
{
name: "if there are no presets, membership reconciliation is a no-op",
- includePreset: []bool{false},
+ includePreset: false,
preExistingOrgMembership: []bool{true, false},
preExistingGroup: []bool{true, false},
preExistingGroupMembership: []bool{true, false},
- expectOrgMembershipExists: ptr.To(false),
- expectGroupExists: ptr.To(false),
+ expectOrgMembershipExists: false,
+ expectGroupExists: false,
+ expectUserInGroup: false,
},
{
name: "if there is a preset, then we should enforce org and group membership in all cases",
- includePreset: []bool{true},
+ includePreset: true,
preExistingOrgMembership: []bool{true, false},
preExistingGroup: []bool{true, false},
preExistingGroupMembership: []bool{true, false},
- expectOrgMembershipExists: ptr.To(true),
- expectGroupExists: ptr.To(true),
- expectUserInGroup: ptr.To(true),
+ expectOrgMembershipExists: true,
+ expectGroupExists: true,
+ expectUserInGroup: true,
},
}
for _, tc := range tests {
tc := tc
- for _, includePreset := range tc.includePreset {
- includePreset := includePreset
- for _, preExistingOrgMembership := range tc.preExistingOrgMembership {
- preExistingOrgMembership := preExistingOrgMembership
- for _, preExistingGroup := range tc.preExistingGroup {
- preExistingGroup := preExistingGroup
- for _, preExistingGroupMembership := range tc.preExistingGroupMembership {
- preExistingGroupMembership := preExistingGroupMembership
- t.Run(tc.name, func(t *testing.T) {
- t.Parallel()
-
- // nolint:gocritic // Reconciliation happens as prebuilds system user, not a human user.
- ctx := dbauthz.AsPrebuildsOrchestrator(testutil.Context(t, testutil.WaitLong))
- _, db := coderdtest.NewWithDatabase(t, nil)
-
- defaultOrg, err := db.GetDefaultOrganization(ctx)
- require.NoError(t, err)
-
- // introduce an unrelated organization to ensure that the membership reconciler doesn't interfere with it.
- unrelatedOrg := dbgen.Organization(t, db, database.Organization{})
- targetOrg := dbgen.Organization(t, db, database.Organization{})
-
- // Ensure membership to unrelated org.
- dbgen.OrganizationMember(t, db, database.OrganizationMember{OrganizationID: unrelatedOrg.ID, UserID: database.PrebuildsSystemUserID})
-
- if preExistingOrgMembership {
- // System user already a member of both orgs.
- dbgen.OrganizationMember(t, db, database.OrganizationMember{OrganizationID: targetOrg.ID, UserID: database.PrebuildsSystemUserID})
- }
+ includePreset := tc.includePreset
+ for _, preExistingOrgMembership := range tc.preExistingOrgMembership {
+ preExistingOrgMembership := preExistingOrgMembership
+ for _, preExistingGroup := range tc.preExistingGroup {
+ preExistingGroup := preExistingGroup
+ for _, preExistingGroupMembership := range tc.preExistingGroupMembership {
+ preExistingGroupMembership := preExistingGroupMembership
+ t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
+
+ // nolint:gocritic // Reconciliation happens as prebuilds system user, not a human user.
+ ctx := dbauthz.AsPrebuildsOrchestrator(testutil.Context(t, testutil.WaitLong))
+ client, db := coderdtest.NewWithDatabase(t, nil)
+ owner := coderdtest.CreateFirstUser(t, client)
+
+ defaultOrg, err := db.GetDefaultOrganization(ctx)
+ require.NoError(t, err)
+
+ // Introduce an unrelated organization to ensure that the membership reconciler doesn't interfere with it.
+ unrelatedOrg := dbgen.Organization(t, db, database.Organization{})
+ dbgen.OrganizationMember(t, db, database.OrganizationMember{OrganizationID: unrelatedOrg.ID, UserID: database.PrebuildsSystemUserID})
+
+ // Organization to test
+ targetOrg := dbgen.Organization(t, db, database.Organization{})
+
+ // Prebuilds system user is a member of the organization
+ if preExistingOrgMembership {
+ dbgen.OrganizationMember(t, db, database.OrganizationMember{OrganizationID: targetOrg.ID, UserID: database.PrebuildsSystemUserID})
+ }
+
+ // Organization has the prebuilds group
+ var prebuildsGroup database.Group
+ if preExistingGroup {
+ prebuildsGroup = dbgen.Group(t, db, database.Group{
+ Name: prebuilds.PrebuiltWorkspacesGroupName,
+ DisplayName: prebuilds.PrebuiltWorkspacesGroupDisplayName,
+ OrganizationID: targetOrg.ID,
+ QuotaAllowance: 0,
+ })
- // Create pre-existing prebuilds group if required by test case
- var prebuildsGroup database.Group
- if preExistingGroup {
- prebuildsGroup = dbgen.Group(t, db, database.Group{
- Name: prebuilds.PrebuiltWorkspacesGroupName,
- DisplayName: prebuilds.PrebuiltWorkspacesGroupDisplayName,
- OrganizationID: targetOrg.ID,
- QuotaAllowance: 0,
+ // Add the system user to the group if required by test case
+ if preExistingGroupMembership {
+ dbgen.GroupMember(t, db, database.GroupMemberTable{
+ GroupID: prebuildsGroup.ID,
+ UserID: database.PrebuildsSystemUserID,
})
-
- // Add the system user to the group if preExistingGroupMembership is true
- if preExistingGroupMembership {
- dbgen.GroupMember(t, db, database.GroupMemberTable{
- GroupID: prebuildsGroup.ID,
- UserID: database.PrebuildsSystemUserID,
- })
- }
}
-
- presets := []database.GetTemplatePresetsWithPrebuildsRow{newPresetRow(unrelatedOrg.ID)}
- if includePreset {
- presets = append(presets, newPresetRow(targetOrg.ID))
- }
-
- // Verify memberships before reconciliation.
- preReconcileMemberships, err := db.GetOrganizationsByUserID(ctx, database.GetOrganizationsByUserIDParams{
- UserID: database.PrebuildsSystemUserID,
- })
- require.NoError(t, err)
- expectedMembershipsBefore := []uuid.UUID{defaultOrg.ID, unrelatedOrg.ID}
- if preExistingOrgMembership {
- expectedMembershipsBefore = append(expectedMembershipsBefore, targetOrg.ID)
- }
- require.ElementsMatch(t, expectedMembershipsBefore, extractOrgIDs(preReconcileMemberships))
-
- // Reconcile
- reconciler := prebuilds.NewStoreMembershipReconciler(db, clock)
- require.NoError(t, reconciler.ReconcileAll(ctx, database.PrebuildsSystemUserID, presets))
-
- // Verify memberships after reconciliation.
- postReconcileMemberships, err := db.GetOrganizationsByUserID(ctx, database.GetOrganizationsByUserIDParams{
- UserID: database.PrebuildsSystemUserID,
- })
+ }
+
+ // Setup unrelated org preset
+ dbfake.TemplateVersion(t, db).Seed(database.TemplateVersion{
+ OrganizationID: unrelatedOrg.ID,
+ CreatedBy: owner.UserID,
+ }).Preset(database.TemplateVersionPreset{
+ DesiredInstances: sql.NullInt32{
+ Int32: 1,
+ Valid: true,
+ },
+ }).Do()
+
+ // Setup target org preset
+ dbfake.TemplateVersion(t, db).Seed(database.TemplateVersion{
+ OrganizationID: targetOrg.ID,
+ CreatedBy: owner.UserID,
+ }).Preset(database.TemplateVersionPreset{
+ DesiredInstances: sql.NullInt32{
+ Int32: 0,
+ Valid: includePreset,
+ },
+ }).Do()
+
+ // Verify memberships before reconciliation.
+ preReconcileMemberships, err := db.GetOrganizationsByUserID(ctx, database.GetOrganizationsByUserIDParams{
+ UserID: database.PrebuildsSystemUserID,
+ })
+ require.NoError(t, err)
+ expectedMembershipsBefore := []uuid.UUID{defaultOrg.ID, unrelatedOrg.ID}
+ if preExistingOrgMembership {
+ expectedMembershipsBefore = append(expectedMembershipsBefore, targetOrg.ID)
+ }
+ require.ElementsMatch(t, expectedMembershipsBefore, extractOrgIDs(preReconcileMemberships))
+
+ // Reconcile
+ reconciler := prebuilds.NewStoreMembershipReconciler(db, clock, slogtest.Make(t, nil))
+ require.NoError(t, reconciler.ReconcileAll(ctx, database.PrebuildsSystemUserID, prebuilds.PrebuiltWorkspacesGroupName))
+
+ // Verify memberships after reconciliation.
+ postReconcileMemberships, err := db.GetOrganizationsByUserID(ctx, database.GetOrganizationsByUserIDParams{
+ UserID: database.PrebuildsSystemUserID,
+ })
+ require.NoError(t, err)
+ expectedMembershipsAfter := expectedMembershipsBefore
+ if !preExistingOrgMembership && tc.expectOrgMembershipExists {
+ expectedMembershipsAfter = append(expectedMembershipsAfter, targetOrg.ID)
+ }
+ require.ElementsMatch(t, expectedMembershipsAfter, extractOrgIDs(postReconcileMemberships))
+
+ // Verify prebuilds group behavior based on expected outcomes
+ prebuildsGroup, err = db.GetGroupByOrgAndName(ctx, database.GetGroupByOrgAndNameParams{
+ OrganizationID: targetOrg.ID,
+ Name: prebuilds.PrebuiltWorkspacesGroupName,
+ })
+ if tc.expectGroupExists {
require.NoError(t, err)
- expectedMembershipsAfter := expectedMembershipsBefore
- if !preExistingOrgMembership && tc.expectOrgMembershipExists != nil && *tc.expectOrgMembershipExists {
- expectedMembershipsAfter = append(expectedMembershipsAfter, targetOrg.ID)
- }
- require.ElementsMatch(t, expectedMembershipsAfter, extractOrgIDs(postReconcileMemberships))
-
- // Verify prebuilds group behavior based on expected outcomes
- prebuildsGroup, err = db.GetGroupByOrgAndName(ctx, database.GetGroupByOrgAndNameParams{
- OrganizationID: targetOrg.ID,
- Name: prebuilds.PrebuiltWorkspacesGroupName,
- })
- if tc.expectGroupExists != nil && *tc.expectGroupExists {
+ require.Equal(t, prebuilds.PrebuiltWorkspacesGroupName, prebuildsGroup.Name)
+ require.Equal(t, prebuilds.PrebuiltWorkspacesGroupDisplayName, prebuildsGroup.DisplayName)
+ require.Equal(t, int32(0), prebuildsGroup.QuotaAllowance) // Default quota should be 0
+
+ if tc.expectUserInGroup {
+ // Check that the system user is a member of the prebuilds group
+ groupMembers, err := db.GetGroupMembersByGroupID(ctx, database.GetGroupMembersByGroupIDParams{
+ GroupID: prebuildsGroup.ID,
+ IncludeSystem: true,
+ })
require.NoError(t, err)
- require.Equal(t, prebuilds.PrebuiltWorkspacesGroupName, prebuildsGroup.Name)
- require.Equal(t, prebuilds.PrebuiltWorkspacesGroupDisplayName, prebuildsGroup.DisplayName)
- require.Equal(t, int32(0), prebuildsGroup.QuotaAllowance) // Default quota should be 0
-
- if tc.expectUserInGroup != nil && *tc.expectUserInGroup {
- // Check that the system user is a member of the prebuilds group
- groupMembers, err := db.GetGroupMembersByGroupID(ctx, database.GetGroupMembersByGroupIDParams{
- GroupID: prebuildsGroup.ID,
- IncludeSystem: true,
- })
- require.NoError(t, err)
- require.Len(t, groupMembers, 1)
- require.Equal(t, database.PrebuildsSystemUserID, groupMembers[0].UserID)
- }
-
- // If no preset exists, then we do not enforce group membership:
- if tc.expectUserInGroup != nil && !*tc.expectUserInGroup {
- // Check that the system user is NOT a member of the prebuilds group
- groupMembers, err := db.GetGroupMembersByGroupID(ctx, database.GetGroupMembersByGroupIDParams{
- GroupID: prebuildsGroup.ID,
- IncludeSystem: true,
- })
- require.NoError(t, err)
- require.Len(t, groupMembers, 0)
- }
+ require.Len(t, groupMembers, 1)
+ require.Equal(t, database.PrebuildsSystemUserID, groupMembers[0].UserID)
}
- if !preExistingGroup && tc.expectGroupExists != nil && !*tc.expectGroupExists {
- // Verify that no prebuilds group exists
- require.Error(t, err)
- require.True(t, errors.Is(err, sql.ErrNoRows))
+ // If no preset exists, then we do not enforce group membership:
+ if !tc.expectUserInGroup {
+ // Check that the system user is NOT a member of the prebuilds group
+ groupMembers, err := db.GetGroupMembersByGroupID(ctx, database.GetGroupMembersByGroupIDParams{
+ GroupID: prebuildsGroup.ID,
+ IncludeSystem: true,
+ })
+ require.NoError(t, err)
+ require.Len(t, groupMembers, 0)
}
- })
- }
+ }
+
+ if !preExistingGroup && !tc.expectGroupExists {
+ // Verify that no prebuilds group exists
+ require.Error(t, err)
+ require.True(t, errors.Is(err, sql.ErrNoRows))
+ }
+ })
}
}
}
diff --git a/enterprise/coderd/prebuilds/metricscollector_test.go b/enterprise/coderd/prebuilds/metricscollector_test.go
index f9584e9ec2c25..aa9886fb7ad1b 100644
--- a/enterprise/coderd/prebuilds/metricscollector_test.go
+++ b/enterprise/coderd/prebuilds/metricscollector_test.go
@@ -485,7 +485,7 @@ func TestMetricsCollector_ReconciliationPausedMetric(t *testing.T) {
require.NoError(t, err)
// Run reconciliation to update the metric
- err = reconciler.ReconcileAll(ctx)
+ _, err = reconciler.ReconcileAll(ctx)
require.NoError(t, err)
// Check that the metric shows reconciliation is not paused
@@ -514,7 +514,7 @@ func TestMetricsCollector_ReconciliationPausedMetric(t *testing.T) {
require.NoError(t, err)
// Run reconciliation to update the metric
- err = reconciler.ReconcileAll(ctx)
+ _, err = reconciler.ReconcileAll(ctx)
require.NoError(t, err)
// Check that the metric shows reconciliation is paused
@@ -543,7 +543,7 @@ func TestMetricsCollector_ReconciliationPausedMetric(t *testing.T) {
require.NoError(t, err)
// Run reconciliation to update the metric
- err = reconciler.ReconcileAll(ctx)
+ _, err = reconciler.ReconcileAll(ctx)
require.NoError(t, err)
// Check that the metric shows reconciliation is not paused
diff --git a/enterprise/coderd/prebuilds/reconcile.go b/enterprise/coderd/prebuilds/reconcile.go
index ceb16061bd7a7..f280436ea98c8 100644
--- a/enterprise/coderd/prebuilds/reconcile.go
+++ b/enterprise/coderd/prebuilds/reconcile.go
@@ -15,6 +15,7 @@ import (
"github.com/google/uuid"
"github.com/hashicorp/go-multierror"
"github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promauto"
"golang.org/x/sync/errgroup"
"golang.org/x/xerrors"
@@ -44,7 +45,6 @@ type StoreReconciler struct {
logger slog.Logger
clock quartz.Clock
registerer prometheus.Registerer
- metrics *MetricsCollector
notifEnq notifications.Enqueuer
buildUsageChecker *atomic.Pointer[wsbuilder.UsageChecker]
@@ -53,10 +53,33 @@ type StoreReconciler struct {
stopped atomic.Bool
done chan struct{}
provisionNotifyCh chan database.ProvisionerJob
+
+ // Prebuild state metrics
+ metrics *MetricsCollector
+ // Operational metrics
+ reconciliationDuration prometheus.Histogram
}
var _ prebuilds.ReconciliationOrchestrator = &StoreReconciler{}
+type DeprovisionMode int
+
+const (
+ DeprovisionModeNormal DeprovisionMode = iota
+ DeprovisionModeOrphan
+)
+
+func (d DeprovisionMode) String() string {
+ switch d {
+ case DeprovisionModeOrphan:
+ return "orphan"
+ case DeprovisionModeNormal:
+ return "normal"
+ default:
+ return "unknown"
+ }
+}
+
func NewStoreReconciler(store database.Store,
ps pubsub.Pubsub,
fileCache *files.Cache,
@@ -87,6 +110,15 @@ func NewStoreReconciler(store database.Store,
// If the registerer fails to register the metrics collector, it's not fatal.
logger.Error(context.Background(), "failed to register prometheus metrics", slog.Error(err))
}
+
+ factory := promauto.With(registerer)
+ reconciler.reconciliationDuration = factory.NewHistogram(prometheus.HistogramOpts{
+ Namespace: "coderd",
+ Subsystem: "prebuilds",
+ Name: "reconciliation_duration_seconds",
+ Help: "Duration of each prebuilds reconciliation cycle.",
+ Buckets: prometheus.DefBuckets,
+ })
}
return reconciler
@@ -158,10 +190,15 @@ func (c *StoreReconciler) Run(ctx context.Context) {
// instead of waiting for the next reconciliation interval
case <-ticker.C:
// Trigger a new iteration on each tick.
- err := c.ReconcileAll(ctx)
+ stats, err := c.ReconcileAll(ctx)
if err != nil {
c.logger.Error(context.Background(), "reconciliation failed", slog.Error(err))
}
+
+ if c.reconciliationDuration != nil {
+ c.reconciliationDuration.Observe(stats.Elapsed.Seconds())
+ }
+ c.logger.Debug(ctx, "reconciliation stats", slog.F("elapsed", stats.Elapsed))
case <-ctx.Done():
// nolint:gocritic // it's okay to use slog.F() for an error in this case
// because we want to differentiate two different types of errors: ctx.Err() and context.Cause()
@@ -245,19 +282,24 @@ func (c *StoreReconciler) Stop(ctx context.Context, cause error) {
// be reconciled again, leading to another workspace being provisioned. Two workspace builds will be occurring
// simultaneously for the same preset, but once both jobs have completed the reconciliation loop will notice the
// extraneous instance and delete it.
-func (c *StoreReconciler) ReconcileAll(ctx context.Context) error {
+func (c *StoreReconciler) ReconcileAll(ctx context.Context) (stats prebuilds.ReconcileStats, err error) {
+ start := c.clock.Now()
+ defer func() {
+ stats.Elapsed = c.clock.Since(start)
+ }()
+
logger := c.logger.With(slog.F("reconcile_context", "all"))
select {
case <-ctx.Done():
logger.Warn(context.Background(), "reconcile exiting prematurely; context done", slog.Error(ctx.Err()))
- return nil
+ return stats, nil
default:
}
logger.Debug(ctx, "starting reconciliation")
- err := c.WithReconciliationLock(ctx, logger, func(ctx context.Context, _ database.Store) error {
+ err = c.WithReconciliationLock(ctx, logger, func(ctx context.Context, _ database.Store) error {
// Check if prebuilds reconciliation is paused
settingsJSON, err := c.store.GetPrebuildsSettings(ctx)
if err != nil {
@@ -280,6 +322,12 @@ func (c *StoreReconciler) ReconcileAll(ctx context.Context) error {
return nil
}
+ membershipReconciler := NewStoreMembershipReconciler(c.store, c.clock, logger)
+ err = membershipReconciler.ReconcileAll(ctx, database.PrebuildsSystemUserID, PrebuiltWorkspacesGroupName)
+ if err != nil {
+ return xerrors.Errorf("reconcile prebuild membership: %w", err)
+ }
+
snapshot, err := c.SnapshotState(ctx, c.store)
if err != nil {
return xerrors.Errorf("determine current snapshot: %w", err)
@@ -292,12 +340,6 @@ func (c *StoreReconciler) ReconcileAll(ctx context.Context) error {
return nil
}
- membershipReconciler := NewStoreMembershipReconciler(c.store, c.clock)
- err = membershipReconciler.ReconcileAll(ctx, database.PrebuildsSystemUserID, snapshot.Presets)
- if err != nil {
- return xerrors.Errorf("reconcile prebuild membership: %w", err)
- }
-
var eg errgroup.Group
// Reconcile presets in parallel. Each preset in its own goroutine.
for _, preset := range snapshot.Presets {
@@ -330,7 +372,7 @@ func (c *StoreReconciler) ReconcileAll(ctx context.Context) error {
logger.Error(ctx, "failed to reconcile", slog.Error(err))
}
- return err
+ return stats, err
}
func (c *StoreReconciler) reportHardLimitedPresets(snapshot *prebuilds.GlobalSnapshot) {
@@ -642,34 +684,7 @@ func (c *StoreReconciler) executeReconciliationAction(ctx context.Context, logge
return multiErr.ErrorOrNil()
case prebuilds.ActionTypeCancelPending:
- // Cancel pending prebuild jobs from non-active template versions to avoid
- // provisioning obsolete workspaces that would immediately be deprovisioned.
- // This uses a criteria-based update to ensure only jobs that are still pending
- // at execution time are canceled, avoiding race conditions where jobs may have
- // transitioned to running status between query and update.
- canceledJobs, err := c.store.UpdatePrebuildProvisionerJobWithCancel(
- ctx,
- database.UpdatePrebuildProvisionerJobWithCancelParams{
- Now: c.clock.Now(),
- PresetID: uuid.NullUUID{
- UUID: ps.Preset.ID,
- Valid: true,
- },
- })
- if err != nil {
- logger.Error(ctx, "failed to cancel pending prebuild jobs",
- slog.F("template_version_id", ps.Preset.TemplateVersionID.String()),
- slog.F("preset_id", ps.Preset.ID),
- slog.Error(err))
- return err
- }
- if len(canceledJobs) > 0 {
- logger.Info(ctx, "canceled pending prebuild jobs for inactive version",
- slog.F("template_version_id", ps.Preset.TemplateVersionID.String()),
- slog.F("preset_id", ps.Preset.ID),
- slog.F("count", len(canceledJobs)))
- }
- return nil
+ return c.cancelAndOrphanDeletePendingPrebuilds(ctx, ps.Preset.TemplateID, ps.Preset.TemplateVersionID, ps.Preset.ID)
default:
return xerrors.Errorf("unknown action type: %v", action.ActionType)
@@ -717,33 +732,100 @@ func (c *StoreReconciler) createPrebuiltWorkspace(ctx context.Context, prebuiltW
c.logger.Info(ctx, "attempting to create prebuild", slog.F("name", name),
slog.F("workspace_id", prebuiltWorkspaceID.String()), slog.F("preset_id", presetID.String()))
- return c.provision(ctx, db, prebuiltWorkspaceID, template, presetID, database.WorkspaceTransitionStart, workspace)
+ return c.provision(ctx, db, prebuiltWorkspaceID, template, presetID, database.WorkspaceTransitionStart, workspace, DeprovisionModeNormal)
}, &database.TxOptions{
Isolation: sql.LevelRepeatableRead,
ReadOnly: false,
})
}
-func (c *StoreReconciler) deletePrebuiltWorkspace(ctx context.Context, prebuiltWorkspaceID uuid.UUID, templateID uuid.UUID, presetID uuid.UUID) error {
+// provisionDelete provisions a delete transition for a prebuilt workspace.
+//
+// If mode is DeprovisionModeOrphan, the builder will not send Terraform state to the provisioner.
+// This allows the workspace to be deleted even when no provisioners are available, and is safe
+// when no Terraform resources were actually created (e.g., for pending prebuilds that were canceled
+// before provisioning started).
+//
+// IMPORTANT: This function must be called within a database transaction. It does not create its own transaction.
+// The caller is responsible for managing the transaction boundary via db.InTx().
+func (c *StoreReconciler) provisionDelete(ctx context.Context, db database.Store, workspaceID uuid.UUID, templateID uuid.UUID, presetID uuid.UUID, mode DeprovisionMode) error {
+ workspace, err := db.GetWorkspaceByID(ctx, workspaceID)
+ if err != nil {
+ return xerrors.Errorf("get workspace by ID: %w", err)
+ }
+
+ template, err := db.GetTemplateByID(ctx, templateID)
+ if err != nil {
+ return xerrors.Errorf("failed to get template: %w", err)
+ }
+
+ if workspace.OwnerID != database.PrebuildsSystemUserID {
+ return xerrors.Errorf("prebuilt workspace is not owned by prebuild user anymore, probably it was claimed")
+ }
+
+ c.logger.Info(ctx, "attempting to delete prebuild", slog.F("orphan", mode.String()),
+ slog.F("name", workspace.Name), slog.F("workspace_id", workspaceID.String()), slog.F("preset_id", presetID.String()))
+
+ return c.provision(ctx, db, workspaceID, template, presetID,
+ database.WorkspaceTransitionDelete, workspace, mode)
+}
+
+// cancelAndOrphanDeletePendingPrebuilds cancels pending prebuild jobs from inactive template versions
+// and orphan-deletes their associated workspaces.
+//
+// The cancel operation uses a criteria-based update to ensure only jobs that are still pending at
+// execution time are canceled, avoiding race conditions where jobs may have transitioned to running.
+//
+// Since these jobs were never processed by a provisioner, no Terraform resources were created,
+// making it safe to orphan-delete the workspaces (skipping Terraform destroy).
+func (c *StoreReconciler) cancelAndOrphanDeletePendingPrebuilds(ctx context.Context, templateID uuid.UUID, templateVersionID uuid.UUID, presetID uuid.UUID) error {
return c.store.InTx(func(db database.Store) error {
- workspace, err := db.GetWorkspaceByID(ctx, prebuiltWorkspaceID)
+ canceledJobs, err := db.UpdatePrebuildProvisionerJobWithCancel(
+ ctx,
+ database.UpdatePrebuildProvisionerJobWithCancelParams{
+ Now: c.clock.Now(),
+ PresetID: uuid.NullUUID{
+ UUID: presetID,
+ Valid: true,
+ },
+ })
if err != nil {
- return xerrors.Errorf("get workspace by ID: %w", err)
+ c.logger.Error(ctx, "failed to cancel pending prebuild jobs",
+ slog.F("template_id", templateID.String()),
+ slog.F("template_version_id", templateVersionID.String()),
+ slog.F("preset_id", presetID.String()),
+ slog.Error(err))
+ return err
}
- template, err := db.GetTemplateByID(ctx, templateID)
- if err != nil {
- return xerrors.Errorf("failed to get template: %w", err)
+ if len(canceledJobs) > 0 {
+ c.logger.Info(ctx, "canceled pending prebuild jobs for inactive version",
+ slog.F("template_id", templateID.String()),
+ slog.F("template_version_id", templateVersionID.String()),
+ slog.F("preset_id", presetID.String()),
+ slog.F("count", len(canceledJobs)))
}
- if workspace.OwnerID != database.PrebuildsSystemUserID {
- return xerrors.Errorf("prebuilt workspace is not owned by prebuild user anymore, probably it was claimed")
+ var multiErr multierror.Error
+ for _, job := range canceledJobs {
+ err = c.provisionDelete(ctx, db, job.WorkspaceID, job.TemplateID, presetID, DeprovisionModeOrphan)
+ if err != nil {
+ c.logger.Error(ctx, "failed to orphan delete canceled prebuild",
+ slog.F("workspace_id", job.WorkspaceID.String()), slog.Error(err))
+ multiErr.Errors = append(multiErr.Errors, err)
+ }
}
- c.logger.Info(ctx, "attempting to delete prebuild",
- slog.F("workspace_id", prebuiltWorkspaceID.String()), slog.F("preset_id", presetID.String()))
+ return multiErr.ErrorOrNil()
+ }, &database.TxOptions{
+ Isolation: sql.LevelRepeatableRead,
+ ReadOnly: false,
+ })
+}
- return c.provision(ctx, db, prebuiltWorkspaceID, template, presetID, database.WorkspaceTransitionDelete, workspace)
+func (c *StoreReconciler) deletePrebuiltWorkspace(ctx context.Context, prebuiltWorkspaceID uuid.UUID, templateID uuid.UUID, presetID uuid.UUID) error {
+ return c.store.InTx(func(db database.Store) error {
+ return c.provisionDelete(ctx, db, prebuiltWorkspaceID, templateID, presetID, DeprovisionModeNormal)
}, &database.TxOptions{
Isolation: sql.LevelRepeatableRead,
ReadOnly: false,
@@ -758,6 +840,7 @@ func (c *StoreReconciler) provision(
presetID uuid.UUID,
transition database.WorkspaceTransition,
workspace database.Workspace,
+ mode DeprovisionMode,
) error {
tvp, err := db.GetPresetParametersByTemplateVersionID(ctx, template.ActiveVersionID)
if err != nil {
@@ -795,6 +878,11 @@ func (c *StoreReconciler) provision(
builder = builder.RichParameterValues(params)
}
+ // Use orphan mode for deletes when no Terraform resources exist
+ if transition == database.WorkspaceTransitionDelete && mode == DeprovisionModeOrphan {
+ builder = builder.Orphan()
+ }
+
_, provisionerJob, _, err := builder.Build(
ctx,
db,
diff --git a/enterprise/coderd/prebuilds/reconcile_test.go b/enterprise/coderd/prebuilds/reconcile_test.go
index 33b99145d8e12..7548faebd7dab 100644
--- a/enterprise/coderd/prebuilds/reconcile_test.go
+++ b/enterprise/coderd/prebuilds/reconcile_test.go
@@ -72,7 +72,8 @@ func TestNoReconciliationActionsIfNoPresets(t *testing.T) {
require.Equal(t, templateVersion, gotTemplateVersion)
// when we trigger the reconciliation loop for all templates
- require.NoError(t, controller.ReconcileAll(ctx))
+ _, err = controller.ReconcileAll(ctx)
+ require.NoError(t, err)
// then no reconciliation actions are taken
// because without presets, there are no prebuilds
@@ -126,7 +127,8 @@ func TestNoReconciliationActionsIfNoPrebuilds(t *testing.T) {
require.NotEmpty(t, presetParameters)
// when we trigger the reconciliation loop for all templates
- require.NoError(t, controller.ReconcileAll(ctx))
+ _, err = controller.ReconcileAll(ctx)
+ require.NoError(t, err)
// then no reconciliation actions are taken
// because without prebuilds, there is nothing to reconcile
@@ -204,7 +206,10 @@ func TestPrebuildReconciliation(t *testing.T) {
templateDeleted: []bool{false},
},
{
- name: "never attempt to interfere with active builds",
+ // TODO(ssncferreira): Investigate why the GetRunningPrebuiltWorkspaces query is returning 0 rows.
+ // When a template version is inactive (templateVersionActive = false), any prebuilds in the
+ // database.ProvisionerJobStatusRunning state should be deleted.
+ name: "never attempt to interfere with prebuilds from an active template version",
// The workspace builder does not allow scheduling a new build if there is already a build
// pending, running, or canceling. As such, we should never attempt to start, stop or delete
// such prebuilds. Rather, we should wait for the existing build to complete and reconcile
@@ -215,7 +220,7 @@ func TestPrebuildReconciliation(t *testing.T) {
database.ProvisionerJobStatusRunning,
database.ProvisionerJobStatusCanceling,
},
- templateVersionActive: []bool{true, false},
+ templateVersionActive: []bool{true},
shouldDeleteOldPrebuild: ptr.To(false),
templateDeleted: []bool{false},
},
@@ -425,7 +430,8 @@ func (tc testCase) run(t *testing.T) {
// Run the reconciliation multiple times to ensure idempotency
// 8 was arbitrary, but large enough to reasonably trust the result
for i := 1; i <= 8; i++ {
- require.NoErrorf(t, controller.ReconcileAll(ctx), "failed on iteration %d", i)
+ _, err := controller.ReconcileAll(ctx)
+ require.NoErrorf(t, err, "failed on iteration %d", i)
if tc.shouldCreateNewPrebuild != nil {
newPrebuildCount := 0
@@ -539,7 +545,8 @@ func TestMultiplePresetsPerTemplateVersion(t *testing.T) {
// Run the reconciliation multiple times to ensure idempotency
// 8 was arbitrary, but large enough to reasonably trust the result
for i := 1; i <= 8; i++ {
- require.NoErrorf(t, controller.ReconcileAll(ctx), "failed on iteration %d", i)
+ _, err := controller.ReconcileAll(ctx)
+ require.NoErrorf(t, err, "failed on iteration %d", i)
newPrebuildCount := 0
workspaces, err := db.GetWorkspacesByTemplateID(ctx, template.ID)
@@ -665,7 +672,7 @@ func TestPrebuildScheduling(t *testing.T) {
DesiredInstances: 5,
})
- err := controller.ReconcileAll(ctx)
+ _, err := controller.ReconcileAll(ctx)
require.NoError(t, err)
// get workspace builds
@@ -748,7 +755,8 @@ func TestInvalidPreset(t *testing.T) {
// Run the reconciliation multiple times to ensure idempotency
// 8 was arbitrary, but large enough to reasonably trust the result
for i := 1; i <= 8; i++ {
- require.NoErrorf(t, controller.ReconcileAll(ctx), "failed on iteration %d", i)
+ _, err := controller.ReconcileAll(ctx)
+ require.NoErrorf(t, err, "failed on iteration %d", i)
workspaces, err := db.GetWorkspacesByTemplateID(ctx, template.ID)
require.NoError(t, err)
@@ -814,7 +822,8 @@ func TestDeletionOfPrebuiltWorkspaceWithInvalidPreset(t *testing.T) {
})
// Old prebuilt workspace should be deleted.
- require.NoError(t, controller.ReconcileAll(ctx))
+ _, err = controller.ReconcileAll(ctx)
+ require.NoError(t, err)
builds, err := db.GetWorkspaceBuildsByWorkspaceID(ctx, database.GetWorkspaceBuildsByWorkspaceIDParams{
WorkspaceID: prebuiltWorkspace.ID,
@@ -913,12 +922,15 @@ func TestSkippingHardLimitedPresets(t *testing.T) {
// Trigger reconciliation to attempt creating a new prebuild.
// The outcome depends on whether the hard limit has been reached.
- require.NoError(t, controller.ReconcileAll(ctx))
+ _, err = controller.ReconcileAll(ctx)
+ require.NoError(t, err)
// These two additional calls to ReconcileAll should not trigger any notifications.
// A notification is only sent once.
- require.NoError(t, controller.ReconcileAll(ctx))
- require.NoError(t, controller.ReconcileAll(ctx))
+ _, err = controller.ReconcileAll(ctx)
+ require.NoError(t, err)
+ _, err = controller.ReconcileAll(ctx)
+ require.NoError(t, err)
// Verify the final state after reconciliation.
workspaces, err = db.GetWorkspacesByTemplateID(ctx, template.ID)
@@ -1090,12 +1102,15 @@ func TestHardLimitedPresetShouldNotBlockDeletion(t *testing.T) {
// Trigger reconciliation to attempt creating a new prebuild.
// The outcome depends on whether the hard limit has been reached.
- require.NoError(t, controller.ReconcileAll(ctx))
+ _, err = controller.ReconcileAll(ctx)
+ require.NoError(t, err)
// These two additional calls to ReconcileAll should not trigger any notifications.
// A notification is only sent once.
- require.NoError(t, controller.ReconcileAll(ctx))
- require.NoError(t, controller.ReconcileAll(ctx))
+ _, err = controller.ReconcileAll(ctx)
+ require.NoError(t, err)
+ _, err = controller.ReconcileAll(ctx)
+ require.NoError(t, err)
// Verify the final state after reconciliation.
// When hard limit is reached, no new workspace should be created.
@@ -1138,7 +1153,8 @@ func TestHardLimitedPresetShouldNotBlockDeletion(t *testing.T) {
}
// Trigger reconciliation to make sure that successful, but outdated prebuilt workspace will be deleted.
- require.NoError(t, controller.ReconcileAll(ctx))
+ _, err = controller.ReconcileAll(ctx)
+ require.NoError(t, err)
workspaces, err = db.GetWorkspacesByTemplateID(ctx, template.ID)
require.NoError(t, err)
@@ -1737,7 +1753,8 @@ func TestExpiredPrebuildsMultipleActions(t *testing.T) {
}
// Trigger reconciliation to process expired prebuilds and enforce desired state.
- require.NoError(t, controller.ReconcileAll(ctx))
+ _, err = controller.ReconcileAll(ctx)
+ require.NoError(t, err)
// Sort non-expired workspaces by CreatedAt in ascending order (oldest first)
sort.Slice(nonExpiredWorkspaces, func(i, j int) bool {
@@ -2121,16 +2138,16 @@ func TestCancelPendingPrebuilds(t *testing.T) {
},
}).SkipCreateTemplate().Do()
- var workspace dbfake.WorkspaceResponse
+ var pendingWorkspace dbfake.WorkspaceResponse
if tt.activeTemplateVersion {
// Given: a prebuilt workspace, workspace build and respective provisioner job from an
// active template version
- workspace = tt.setupBuild(t, db, client,
+ pendingWorkspace = tt.setupBuild(t, db, client,
owner.OrganizationID, templateID, activeTemplateVersion.TemplateVersion.ID, activePresetID)
} else {
// Given: a prebuilt workspace, workspace build and respective provisioner job from a
// non-active template version
- workspace = tt.setupBuild(t, db, client,
+ pendingWorkspace = tt.setupBuild(t, db, client,
owner.OrganizationID, templateID, nonActiveTemplateVersion.TemplateVersion.ID, nonActivePresetID)
}
@@ -2142,18 +2159,32 @@ func TestCancelPendingPrebuilds(t *testing.T) {
require.NoError(t, err)
// When: the reconciliation loop is triggered
- require.NoError(t, reconciler.ReconcileAll(ctx))
+ _, err = reconciler.ReconcileAll(ctx)
+ require.NoError(t, err)
if tt.shouldCancel {
- // Then: the prebuild related jobs from non-active version should be canceled
- cancelledJob, err := db.GetProvisionerJobByID(ctx, workspace.Build.JobID)
+ // Then: the pending prebuild job from non-active version should be canceled
+ cancelledJob, err := db.GetProvisionerJobByID(ctx, pendingWorkspace.Build.JobID)
require.NoError(t, err)
require.Equal(t, clock.Now().UTC(), cancelledJob.CanceledAt.Time.UTC())
require.Equal(t, clock.Now().UTC(), cancelledJob.CompletedAt.Time.UTC())
require.Equal(t, database.ProvisionerJobStatusCanceled, cancelledJob.JobStatus)
+
+ // Then: the workspace should be deleted
+ deletedWorkspace, err := db.GetWorkspaceByID(ctx, pendingWorkspace.Workspace.ID)
+ require.NoError(t, err)
+ require.True(t, deletedWorkspace.Deleted)
+ latestBuild, err := db.GetLatestWorkspaceBuildByWorkspaceID(ctx, deletedWorkspace.ID)
+ require.NoError(t, err)
+ require.Equal(t, database.WorkspaceTransitionDelete, latestBuild.Transition)
+ deleteJob, err := db.GetProvisionerJobByID(ctx, latestBuild.JobID)
+ require.NoError(t, err)
+ require.True(t, deleteJob.CompletedAt.Valid)
+ require.False(t, deleteJob.WorkerID.Valid)
+ require.Equal(t, database.ProvisionerJobStatusSucceeded, deleteJob.JobStatus)
} else {
- // Then: the provisioner job should not be canceled
- job, err := db.GetProvisionerJobByID(ctx, workspace.Build.JobID)
+ // Then: the pending prebuild job should not be canceled
+ job, err := db.GetProvisionerJobByID(ctx, pendingWorkspace.Build.JobID)
require.NoError(t, err)
if !tt.previouslyCanceled {
require.Zero(t, job.CanceledAt.Time.UTC())
@@ -2162,6 +2193,11 @@ func TestCancelPendingPrebuilds(t *testing.T) {
if !tt.previouslyCompleted {
require.Zero(t, job.CompletedAt.Time.UTC())
}
+
+ // Then: the workspace should not be deleted
+ workspace, err := db.GetWorkspaceByID(ctx, pendingWorkspace.Workspace.ID)
+ require.NoError(t, err)
+ require.False(t, workspace.Deleted)
}
})
}
@@ -2235,25 +2271,45 @@ func TestCancelPendingPrebuilds(t *testing.T) {
return prebuilds
}
- checkIfJobCanceled := func(
+ checkIfJobCanceledAndDeleted := func(
t *testing.T,
clock *quartz.Mock,
ctx context.Context,
db database.Store,
- shouldBeCanceled bool,
+ shouldBeCanceledAndDeleted bool,
prebuilds []dbfake.WorkspaceResponse,
) {
for _, prebuild := range prebuilds {
- job, err := db.GetProvisionerJobByID(ctx, prebuild.Build.JobID)
+ pendingJob, err := db.GetProvisionerJobByID(ctx, prebuild.Build.JobID)
require.NoError(t, err)
- if shouldBeCanceled {
- require.Equal(t, database.ProvisionerJobStatusCanceled, job.JobStatus)
- require.Equal(t, clock.Now().UTC(), job.CanceledAt.Time.UTC())
- require.Equal(t, clock.Now().UTC(), job.CompletedAt.Time.UTC())
+ if shouldBeCanceledAndDeleted {
+ // Pending job should be canceled
+ require.Equal(t, database.ProvisionerJobStatusCanceled, pendingJob.JobStatus)
+ require.Equal(t, clock.Now().UTC(), pendingJob.CanceledAt.Time.UTC())
+ require.Equal(t, clock.Now().UTC(), pendingJob.CompletedAt.Time.UTC())
+
+ // Workspace should be deleted
+ deletedWorkspace, err := db.GetWorkspaceByID(ctx, prebuild.Workspace.ID)
+ require.NoError(t, err)
+ require.True(t, deletedWorkspace.Deleted)
+ latestBuild, err := db.GetLatestWorkspaceBuildByWorkspaceID(ctx, deletedWorkspace.ID)
+ require.NoError(t, err)
+ require.Equal(t, database.WorkspaceTransitionDelete, latestBuild.Transition)
+ deleteJob, err := db.GetProvisionerJobByID(ctx, latestBuild.JobID)
+ require.NoError(t, err)
+ require.True(t, deleteJob.CompletedAt.Valid)
+ require.False(t, deleteJob.WorkerID.Valid)
+ require.Equal(t, database.ProvisionerJobStatusSucceeded, deleteJob.JobStatus)
} else {
- require.NotEqual(t, database.ProvisionerJobStatusCanceled, job.JobStatus)
- require.Zero(t, job.CanceledAt.Time.UTC())
+ // Pending job should not be canceled
+ require.NotEqual(t, database.ProvisionerJobStatusCanceled, pendingJob.JobStatus)
+ require.Zero(t, pendingJob.CanceledAt.Time.UTC())
+
+ // Workspace should not be deleted
+ workspace, err := db.GetWorkspaceByID(ctx, prebuild.Workspace.ID)
+ require.NoError(t, err)
+ require.False(t, workspace.Deleted)
}
}
}
@@ -2306,26 +2362,72 @@ func TestCancelPendingPrebuilds(t *testing.T) {
templateBVersion3Pending := setupPrebuilds(t, db, owner.OrganizationID, templateBID, templateBVersion3ID, templateBVersion3PresetID, 1, true)
// When: the reconciliation loop is executed
- require.NoError(t, reconciler.ReconcileAll(ctx))
+ _, err := reconciler.ReconcileAll(ctx)
+ require.NoError(t, err)
// Then: template A version 1 running workspaces should not be canceled
- checkIfJobCanceled(t, clock, ctx, db, false, templateAVersion1Running)
+ checkIfJobCanceledAndDeleted(t, clock, ctx, db, false, templateAVersion1Running)
// Then: template A version 1 pending workspaces should be canceled
- checkIfJobCanceled(t, clock, ctx, db, true, templateAVersion1Pending)
+ checkIfJobCanceledAndDeleted(t, clock, ctx, db, true, templateAVersion1Pending)
// Then: template A version 2 running and pending workspaces should not be canceled
- checkIfJobCanceled(t, clock, ctx, db, false, templateAVersion2Running)
- checkIfJobCanceled(t, clock, ctx, db, false, templateAVersion2Pending)
+ checkIfJobCanceledAndDeleted(t, clock, ctx, db, false, templateAVersion2Running)
+ checkIfJobCanceledAndDeleted(t, clock, ctx, db, false, templateAVersion2Pending)
// Then: template B version 1 running workspaces should not be canceled
- checkIfJobCanceled(t, clock, ctx, db, false, templateBVersion1Running)
+ checkIfJobCanceledAndDeleted(t, clock, ctx, db, false, templateBVersion1Running)
// Then: template B version 1 pending workspaces should be canceled
- checkIfJobCanceled(t, clock, ctx, db, true, templateBVersion1Pending)
+ checkIfJobCanceledAndDeleted(t, clock, ctx, db, true, templateBVersion1Pending)
// Then: template B version 2 pending workspaces should be canceled
- checkIfJobCanceled(t, clock, ctx, db, true, templateBVersion2Pending)
+ checkIfJobCanceledAndDeleted(t, clock, ctx, db, true, templateBVersion2Pending)
// Then: template B version 3 running and pending workspaces should not be canceled
- checkIfJobCanceled(t, clock, ctx, db, false, templateBVersion3Running)
- checkIfJobCanceled(t, clock, ctx, db, false, templateBVersion3Pending)
+ checkIfJobCanceledAndDeleted(t, clock, ctx, db, false, templateBVersion3Running)
+ checkIfJobCanceledAndDeleted(t, clock, ctx, db, false, templateBVersion3Pending)
+ })
+}
+
+func TestReconciliationStats(t *testing.T) {
+ t.Parallel()
+
+ // Setup
+ clock := quartz.NewReal()
+ db, ps := dbtestutil.NewDB(t)
+ client, _, _ := coderdtest.NewWithAPI(t, &coderdtest.Options{
+ Database: db,
+ Pubsub: ps,
+ Clock: clock,
})
+ fakeEnqueuer := newFakeEnqueuer()
+ registry := prometheus.NewRegistry()
+ cache := files.New(registry, &coderdtest.FakeAuthorizer{})
+ logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: false}).Leveled(slog.LevelDebug)
+ reconciler := prebuilds.NewStoreReconciler(db, ps, cache, codersdk.PrebuildsConfig{}, logger, clock, registry, fakeEnqueuer, newNoopUsageCheckerPtr())
+ owner := coderdtest.CreateFirstUser(t, client)
+
+ ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
+ defer cancel()
+
+ // Create a template version with a preset
+ dbfake.TemplateVersion(t, db).Seed(database.TemplateVersion{
+ OrganizationID: owner.OrganizationID,
+ CreatedBy: owner.UserID,
+ }).Preset(database.TemplateVersionPreset{
+ DesiredInstances: sql.NullInt32{
+ Int32: 1,
+ Valid: true,
+ },
+ }).Do()
+
+ // Verify that ReconcileAll tracks and returns elapsed time
+ start := time.Now()
+ stats, err := reconciler.ReconcileAll(ctx)
+ actualElapsed := time.Since(start)
+ require.NoError(t, err)
+ require.Greater(t, stats.Elapsed, time.Duration(0))
+
+ // Verify stats.Elapsed matches actual execution time
+ require.InDelta(t, actualElapsed.Milliseconds(), stats.Elapsed.Milliseconds(), 100)
+ // Verify reconciliation loop is not unexpectedly slow
+ require.Less(t, stats.Elapsed, 5*time.Second)
}
func newNoopEnqueuer() *notifications.NoopEnqueuer {
@@ -2822,7 +2924,7 @@ func TestReconciliationRespectsPauseSetting(t *testing.T) {
_ = setupTestDBPreset(t, db, templateVersionID, 2, "test")
// Initially, reconciliation should create prebuilds
- err := reconciler.ReconcileAll(ctx)
+ _, err := reconciler.ReconcileAll(ctx)
require.NoError(t, err)
// Verify that prebuilds were created
@@ -2849,7 +2951,7 @@ func TestReconciliationRespectsPauseSetting(t *testing.T) {
require.Len(t, workspaces, 0, "prebuilds should be deleted")
// Run reconciliation again - it should be paused and not recreate prebuilds
- err = reconciler.ReconcileAll(ctx)
+ _, err = reconciler.ReconcileAll(ctx)
require.NoError(t, err)
// Verify that no new prebuilds were created because reconciliation is paused
@@ -2862,7 +2964,7 @@ func TestReconciliationRespectsPauseSetting(t *testing.T) {
require.NoError(t, err)
// Run reconciliation again - it should now recreate the prebuilds
- err = reconciler.ReconcileAll(ctx)
+ _, err = reconciler.ReconcileAll(ctx)
require.NoError(t, err)
// Verify that prebuilds were recreated
diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts
index d671cc2bb117e..8d86362b06227 100644
--- a/site/src/api/typesGenerated.ts
+++ b/site/src/api/typesGenerated.ts
@@ -1894,7 +1894,6 @@ export const EntitlementsWarningHeader = "X-Coder-Entitlements-Warning";
// From codersdk/deployment.go
export type Experiment =
- | "aibridge"
| "auto-fill-parameters"
| "example"
| "mcp-server-http"
@@ -1905,7 +1904,6 @@ export type Experiment =
| "workspace-usage";
export const Experiments: Experiment[] = [
- "aibridge",
"auto-fill-parameters",
"example",
"mcp-server-http",
@@ -5877,6 +5875,10 @@ export interface Workspace {
* and IsPrebuild returns false.
*/
readonly is_prebuild: boolean;
+ /**
+ * TaskID, if set, indicates that the workspace is relevant to the given codersdk.Task.
+ */
+ readonly task_id?: string;
}
// From codersdk/workspaces.go
@@ -6397,10 +6399,9 @@ export interface WorkspaceBuild {
readonly template_version_preset_id: string | null;
readonly has_ai_task?: boolean;
/**
- * Deprecated: This field has been replaced with `TaskAppID`
+ * Deprecated: This field has been replaced with `Task.WorkspaceAppID`
*/
readonly ai_task_sidebar_app_id?: string;
- readonly task_app_id?: string;
readonly has_external_agent?: boolean;
}
diff --git a/site/src/modules/tasks/TaskPrompt/TaskPrompt.stories.tsx b/site/src/modules/tasks/TaskPrompt/TaskPrompt.stories.tsx
index 9572c68c75259..8187ec7500f87 100644
--- a/site/src/modules/tasks/TaskPrompt/TaskPrompt.stories.tsx
+++ b/site/src/modules/tasks/TaskPrompt/TaskPrompt.stories.tsx
@@ -480,3 +480,123 @@ export const CheckExternalAuthOnChangingVersions: Story = {
});
},
};
+
+export const CheckPresetsWhenChangingTemplate: Story = {
+ args: {
+ templates: [
+ {
+ ...MockTemplate,
+ id: "claude-code",
+ name: "claude-code",
+ display_name: "Claude Code",
+ active_version_id: "claude-code-version",
+ },
+ {
+ ...MockTemplate,
+ id: "codex",
+ name: "codex",
+ display_name: "Codex",
+ active_version_id: "codex-version",
+ },
+ ],
+ },
+ beforeEach: () => {
+ spyOn(API, "getTemplateVersionPresets").mockImplementation((versionId) => {
+ if (versionId === "claude-code-version") {
+ return Promise.resolve([
+ {
+ ...MockPresets[0],
+ ID: "claude-code-preset-1",
+ Name: "Claude Code Dev",
+ },
+ ]);
+ }
+ if (versionId === "codex-version") {
+ return Promise.resolve([
+ {
+ ...MockPresets[0],
+ ID: "codex-preset-1",
+ Name: "Codex Dev",
+ },
+ ]);
+ }
+ return Promise.resolve([]);
+ });
+ spyOn(API, "getTemplateVersions").mockImplementation((templateId) => {
+ if (templateId === "claude-code") {
+ return Promise.resolve([
+ {
+ ...MockTemplateVersion,
+ id: "claude-code-version",
+ name: "claude-code-version",
+ },
+ ]);
+ }
+ if (templateId === "codex") {
+ return Promise.resolve([
+ {
+ ...MockTemplateVersion,
+ id: "codex-version",
+ name: "codex-version",
+ },
+ ]);
+ }
+ return Promise.resolve([]);
+ });
+ },
+ play: async ({ canvasElement, step }) => {
+ const canvas = within(canvasElement);
+ const body = within(canvasElement.ownerDocument.body);
+
+ await step("Presets are initially present", async () => {
+ const presetSelect = await canvas.findByLabelText(/preset/i);
+ await userEvent.click(presetSelect);
+
+ const options = await body.findAllByRole("option");
+ expect(options).toHaveLength(1);
+ expect(options[0]).toContainHTML("Claude Code Dev");
+
+ await userEvent.click(options[0]);
+ });
+
+ await step("Switch template", async () => {
+ const templateSelect = await canvas.findByLabelText(/select template/i);
+ await userEvent.click(templateSelect);
+
+ const codexTemplateOption = await body.findByRole("option", {
+ name: /codex/i,
+ });
+ await userEvent.click(codexTemplateOption);
+ });
+
+ await step("Presets are present in new template", async () => {
+ const presetSelect = await canvas.findByLabelText(/preset/i);
+ await userEvent.click(presetSelect);
+
+ const options = await body.findAllByRole("option");
+ expect(options).toHaveLength(1);
+ expect(options[0]).toContainHTML("Codex Dev");
+
+ await userEvent.click(options[0]);
+ });
+
+ await step("Switch template back", async () => {
+ const templateSelect = await canvas.findByLabelText(/select template/i);
+ await userEvent.click(templateSelect);
+
+ const codexTemplateOption = await body.findByRole("option", {
+ name: /claude code/i,
+ });
+ await userEvent.click(codexTemplateOption);
+ });
+
+ await step("Presets are present in original template", async () => {
+ const presetSelect = await canvas.findByLabelText(/preset/i);
+ await userEvent.click(presetSelect);
+
+ const options = await body.findAllByRole("option");
+ expect(options).toHaveLength(1);
+ expect(options[0]).toContainHTML("Claude Code Dev");
+ });
+ },
+};
diff --git a/site/src/modules/tasks/TaskPrompt/TaskPrompt.tsx b/site/src/modules/tasks/TaskPrompt/TaskPrompt.tsx
index b40f3253a8e93..677a24eaabf16 100644
--- a/site/src/modules/tasks/TaskPrompt/TaskPrompt.tsx
+++ b/site/src/modules/tasks/TaskPrompt/TaskPrompt.tsx
@@ -270,7 +270,12 @@ const CreateTaskForm: FC