Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit73d0bdf

Browse files
committed
fixes
1 parente07c236 commit73d0bdf

File tree

8 files changed

+114
-80
lines changed

8 files changed

+114
-80
lines changed

‎coderd/coderd.go‎

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,43 +1000,40 @@ func New(options *Options) *API {
10001000

10011001
// Experimental routes are not guaranteed to be stable and may change at any time.
10021002
r.Route("/api/experimental",func(r chi.Router) {
1003-
r.NotFound(func(rw http.ResponseWriter,_*http.Request) {httpapi.RouteNotFound(rw) })
1003+
api.ExperimentalHandler=r
10041004

1005-
// Only this group should be subject to apiKeyMiddleware; aibridged will mount its own
1006-
// router and handles key validation in a different fashion.
1007-
// See enterprise/x/aibridged/http.go.
1008-
r.Group(func(r chi.Router) {
1005+
r.NotFound(func(rw http.ResponseWriter,_*http.Request) {httpapi.RouteNotFound(rw) })
1006+
r.Use(
1007+
// Specific routes can specify different limits, but every rate
1008+
// limit must be configurable by the admin.
1009+
apiRateLimiter,
1010+
httpmw.ReportCLITelemetry(api.Logger,options.Telemetry),
1011+
)
1012+
r.Route("/aitasks",func(r chi.Router) {
1013+
r.Use(apiKeyMiddleware)
1014+
r.Get("/prompts",api.aiTasksPrompts)
1015+
})
1016+
r.Route("/tasks",func(r chi.Router) {
10091017
r.Use(apiKeyMiddleware)
1010-
r.Route("/aibridge",func(r chi.Router) {
1011-
r.Use(
1012-
httpmw.RequireExperimentWithDevBypass(api.Experiments,codersdk.ExperimentAIBridge),
1013-
)
1014-
r.Get("/interceptions",api.aiBridgeListInterceptions)
1015-
})
1016-
r.Route("/aitasks",func(r chi.Router) {
1017-
r.Get("/prompts",api.aiTasksPrompts)
1018-
})
1019-
r.Route("/tasks",func(r chi.Router) {
1020-
r.Use(apiRateLimiter)
10211018

1022-
r.Get("/",api.tasksList)
1019+
r.Get("/",api.tasksList)
10231020

1024-
r.Route("/{user}",func(r chi.Router) {
1025-
r.Use(httpmw.ExtractOrganizationMembersParam(options.Database,api.HTTPAuth.Authorize))
1026-
r.Get("/{id}",api.taskGet)
1027-
r.Delete("/{id}",api.taskDelete)
1028-
r.Post("/{id}/send",api.taskSend)
1029-
r.Post("/",api.tasksCreate)
1030-
})
1031-
})
1032-
r.Route("/mcp",func(r chi.Router) {
1033-
r.Use(
1034-
httpmw.RequireExperimentWithDevBypass(api.Experiments,codersdk.ExperimentOAuth2,codersdk.ExperimentMCPServerHTTP),
1035-
)
1036-
// MCP HTTP transport endpoint with mandatory authentication
1037-
r.Mount("/http",api.mcpHTTPHandler())
1021+
r.Route("/{user}",func(r chi.Router) {
1022+
r.Use(httpmw.ExtractOrganizationMembersParam(options.Database,api.HTTPAuth.Authorize))
1023+
r.Get("/{id}",api.taskGet)
1024+
r.Delete("/{id}",api.taskDelete)
1025+
r.Post("/{id}/send",api.taskSend)
1026+
r.Post("/",api.tasksCreate)
10381027
})
10391028
})
1029+
r.Route("/mcp",func(r chi.Router) {
1030+
r.Use(
1031+
apiKeyMiddleware,
1032+
httpmw.RequireExperimentWithDevBypass(api.Experiments,codersdk.ExperimentOAuth2,codersdk.ExperimentMCPServerHTTP),
1033+
)
1034+
// MCP HTTP transport endpoint with mandatory authentication
1035+
r.Mount("/http",api.mcpHTTPHandler())
1036+
})
10401037
})
10411038

10421039
r.Route("/api/v2",func(r chi.Router) {
@@ -1730,6 +1727,8 @@ type API struct {
17301727

17311728
// APIHandler serves "/api/v2"
17321729
APIHandler chi.Router
1730+
// ExperimentalHandler serves "/api/experimental"
1731+
ExperimentalHandler chi.Router
17331732
// RootHandler serves "/"
17341733
RootHandler chi.Router
17351734

‎coderd/database/db2sdk/db2sdk.go‎

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,10 +1000,3 @@ func jsonOrEmptyMap(rawMessage pqtype.NullRawMessage) map[string]any {
10001000
}
10011001
returnm
10021002
}
1003-
1004-
funcensureNonNilSlice[Tany](slice []T) []T {
1005-
ifslice==nil {
1006-
return []T{}
1007-
}
1008-
returnslice
1009-
}

‎coderd/database/dbauthz/dbauthz.go‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4417,34 +4417,34 @@ func (q *querier) ListAIBridgeInterceptions(ctx context.Context, arg database.Li
44174417
returnq.db.ListAuthorizedAIBridgeInterceptions(ctx,arg,prep)
44184418
}
44194419

4420-
func (q*querier)ListAIBridgeTokenUsagesByInterceptionIDs(ctx context.Context,interceptionIds []uuid.UUID) ([]database.AIBridgeTokenUsage,error) {
4420+
func (q*querier)ListAIBridgeTokenUsagesByInterceptionIDs(ctx context.Context,interceptionIDs []uuid.UUID) ([]database.AIBridgeTokenUsage,error) {
44214421
// This function is a system function until we implement a join for aibridge interceptions.
44224422
// Matches the behavior of the workspaces listing endpoint.
44234423
iferr:=q.authorizeContext(ctx,policy.ActionRead,rbac.ResourceSystem);err!=nil {
44244424
returnnil,err
44254425
}
44264426

4427-
returnq.db.ListAIBridgeTokenUsagesByInterceptionIDs(ctx,interceptionIds)
4427+
returnq.db.ListAIBridgeTokenUsagesByInterceptionIDs(ctx,interceptionIDs)
44284428
}
44294429

4430-
func (q*querier)ListAIBridgeToolUsagesByInterceptionIDs(ctx context.Context,interceptionIds []uuid.UUID) ([]database.AIBridgeToolUsage,error) {
4430+
func (q*querier)ListAIBridgeToolUsagesByInterceptionIDs(ctx context.Context,interceptionIDs []uuid.UUID) ([]database.AIBridgeToolUsage,error) {
44314431
// This function is a system function until we implement a join for aibridge interceptions.
44324432
// Matches the behavior of the workspaces listing endpoint.
44334433
iferr:=q.authorizeContext(ctx,policy.ActionRead,rbac.ResourceSystem);err!=nil {
44344434
returnnil,err
44354435
}
44364436

4437-
returnq.db.ListAIBridgeToolUsagesByInterceptionIDs(ctx,interceptionIds)
4437+
returnq.db.ListAIBridgeToolUsagesByInterceptionIDs(ctx,interceptionIDs)
44384438
}
44394439

4440-
func (q*querier)ListAIBridgeUserPromptsByInterceptionIDs(ctx context.Context,interceptionIds []uuid.UUID) ([]database.AIBridgeUserPrompt,error) {
4440+
func (q*querier)ListAIBridgeUserPromptsByInterceptionIDs(ctx context.Context,interceptionIDs []uuid.UUID) ([]database.AIBridgeUserPrompt,error) {
44414441
// This function is a system function until we implement a join for aibridge interceptions.
44424442
// Matches the behavior of the workspaces listing endpoint.
44434443
iferr:=q.authorizeContext(ctx,policy.ActionRead,rbac.ResourceSystem);err!=nil {
44444444
returnnil,err
44454445
}
44464446

4447-
returnq.db.ListAIBridgeUserPromptsByInterceptionIDs(ctx,interceptionIds)
4447+
returnq.db.ListAIBridgeUserPromptsByInterceptionIDs(ctx,interceptionIDs)
44484448
}
44494449

44504450
func (q*querier)ListProvisionerKeysByOrganization(ctx context.Context,organizationID uuid.UUID) ([]database.ProvisionerKey,error) {

‎coderd/database/dbauthz/dbauthz_test.go‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4442,19 +4442,19 @@ func (s *MethodTestSuite) TestAIBridge() {
44424442
}))
44434443

44444444
s.Run("ListAIBridgeTokenUsagesByInterceptionIDs",s.Mocked(func(db*dbmock.MockStore,faker*gofakeit.Faker,check*expects) {
4445-
ids:= []uuid.UUID{uuid.UUID{1}}
4445+
ids:= []uuid.UUID{{1}}
44464446
db.EXPECT().ListAIBridgeTokenUsagesByInterceptionIDs(gomock.Any(),ids).Return([]database.AIBridgeTokenUsage{},nil).AnyTimes()
44474447
check.Args(ids).Asserts(rbac.ResourceSystem,policy.ActionRead).Returns([]database.AIBridgeTokenUsage{})
44484448
}))
44494449

44504450
s.Run("ListAIBridgeUserPromptsByInterceptionIDs",s.Mocked(func(db*dbmock.MockStore,faker*gofakeit.Faker,check*expects) {
4451-
ids:= []uuid.UUID{uuid.UUID{1}}
4451+
ids:= []uuid.UUID{{1}}
44524452
db.EXPECT().ListAIBridgeUserPromptsByInterceptionIDs(gomock.Any(),ids).Return([]database.AIBridgeUserPrompt{},nil).AnyTimes()
44534453
check.Args(ids).Asserts(rbac.ResourceSystem,policy.ActionRead).Returns([]database.AIBridgeUserPrompt{})
44544454
}))
44554455

44564456
s.Run("ListAIBridgeToolUsagesByInterceptionIDs",s.Mocked(func(db*dbmock.MockStore,faker*gofakeit.Faker,check*expects) {
4457-
ids:= []uuid.UUID{uuid.UUID{1}}
4457+
ids:= []uuid.UUID{{1}}
44584458
db.EXPECT().ListAIBridgeToolUsagesByInterceptionIDs(gomock.Any(),ids).Return([]database.AIBridgeToolUsage{},nil).AnyTimes()
44594459
check.Args(ids).Asserts(rbac.ResourceSystem,policy.ActionRead).Returns([]database.AIBridgeToolUsage{})
44604460
}))

‎coderd/aibridge.go‎renamed to ‎enterprise/coderd/aibridge.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/google/uuid"
99
"golang.org/x/xerrors"
1010

11+
"github.com/coder/coder/v2/coderd"
1112
"github.com/coder/coder/v2/coderd/database"
1213
"github.com/coder/coder/v2/coderd/database/db2sdk"
1314
"github.com/coder/coder/v2/coderd/database/dbauthz"
@@ -39,7 +40,7 @@ func (api *API) aiBridgeListInterceptions(rw http.ResponseWriter, r *http.Reques
3940
ctx:=r.Context()
4041
apiKey:=httpmw.APIKey(r)
4142

42-
page,ok:=ParsePagination(rw,r)
43+
page,ok:=coderd.ParsePagination(rw,r)
4344
if!ok {
4445
return
4546
}

‎coderd/aibridge_test.go‎renamed to ‎enterprise/coderd/aibridge_test.go‎

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/coder/coder/v2/coderd/database/dbgen"
1414
"github.com/coder/coder/v2/coderd/database/dbtime"
1515
"github.com/coder/coder/v2/codersdk"
16+
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
1617
"github.com/coder/coder/v2/testutil"
1718
)
1819

@@ -21,8 +22,13 @@ func TestAIBridgeListInterceptions(t *testing.T) {
2122

2223
t.Run("EmptyDB",func(t*testing.T) {
2324
t.Parallel()
24-
client:=coderdtest.New(t,&coderdtest.Options{})
25-
_=coderdtest.CreateFirstUser(t,client)
25+
dv:=coderdtest.DeploymentValues(t)
26+
dv.Experiments= []string{string(codersdk.ExperimentAIBridge)}
27+
client,_:=coderdenttest.New(t,&coderdenttest.Options{
28+
Options:&coderdtest.Options{
29+
DeploymentValues:dv,
30+
},
31+
})
2632
experimentalClient:=codersdk.NewExperimentalClient(client)
2733
ctx:=testutil.Context(t,testutil.WaitLong)
2834
res,err:=experimentalClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{})
@@ -32,8 +38,13 @@ func TestAIBridgeListInterceptions(t *testing.T) {
3238

3339
t.Run("OK",func(t*testing.T) {
3440
t.Parallel()
35-
client,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{})
36-
_=coderdtest.CreateFirstUser(t,client)
41+
dv:=coderdtest.DeploymentValues(t)
42+
dv.Experiments= []string{string(codersdk.ExperimentAIBridge)}
43+
client,db,_:=coderdenttest.NewWithDatabase(t,&coderdenttest.Options{
44+
Options:&coderdtest.Options{
45+
DeploymentValues:dv,
46+
},
47+
})
3748
experimentalClient:=codersdk.NewExperimentalClient(client)
3849
ctx:=testutil.Context(t,testutil.WaitLong)
3950

@@ -108,8 +119,13 @@ func TestAIBridgeListInterceptions(t *testing.T) {
108119
t.Run("Pagination",func(t*testing.T) {
109120
t.Parallel()
110121

111-
client,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{})
112-
_=coderdtest.CreateFirstUser(t,client)
122+
dv:=coderdtest.DeploymentValues(t)
123+
dv.Experiments= []string{string(codersdk.ExperimentAIBridge)}
124+
client,db,_:=coderdenttest.NewWithDatabase(t,&coderdenttest.Options{
125+
Options:&coderdtest.Options{
126+
DeploymentValues:dv,
127+
},
128+
})
113129
experimentalClient:=codersdk.NewExperimentalClient(client)
114130
ctx:=testutil.Context(t,testutil.WaitLong)
115131

@@ -166,9 +182,14 @@ func TestAIBridgeListInterceptions(t *testing.T) {
166182

167183
t.Run("Authorized",func(t*testing.T) {
168184
t.Parallel()
169-
adminClient,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{})
185+
dv:=coderdtest.DeploymentValues(t)
186+
dv.Experiments= []string{string(codersdk.ExperimentAIBridge)}
187+
adminClient,db,firstUser:=coderdenttest.NewWithDatabase(t,&coderdenttest.Options{
188+
Options:&coderdtest.Options{
189+
DeploymentValues:dv,
190+
},
191+
})
170192
adminExperimentalClient:=codersdk.NewExperimentalClient(adminClient)
171-
firstUser:=coderdtest.CreateFirstUser(t,adminClient)
172193
ctx:=testutil.Context(t,testutil.WaitLong)
173194

174195
secondUserClient,secondUser:=coderdtest.CreateAnotherUser(t,adminClient,firstUser.OrganizationID)
@@ -200,11 +221,14 @@ func TestAIBridgeListInterceptions(t *testing.T) {
200221

201222
t.Run("Filter",func(t*testing.T) {
202223
t.Parallel()
203-
client,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{})
204-
firstUser:=coderdtest.CreateFirstUser(t,client)
224+
dv:=coderdtest.DeploymentValues(t)
225+
dv.Experiments= []string{string(codersdk.ExperimentAIBridge)}
226+
client,db,firstUser:=coderdenttest.NewWithDatabase(t,&coderdenttest.Options{
227+
Options:&coderdtest.Options{
228+
DeploymentValues:dv,
229+
},
230+
})
205231
experimentalClient:=codersdk.NewExperimentalClient(client)
206-
ctx:=testutil.Context(t,testutil.WaitLong)
207-
208232
_,secondUser:=coderdtest.CreateAnotherUser(t,client,firstUser.OrganizationID)
209233

210234
// Insert a bunch of test data with varying filterable fields.
@@ -336,6 +360,7 @@ func TestAIBridgeListInterceptions(t *testing.T) {
336360
for_,tc:=rangecases {
337361
t.Run(tc.name,func(t*testing.T) {
338362
t.Parallel()
363+
ctx:=testutil.Context(t,testutil.WaitLong)
339364
res,err:=experimentalClient.AIBridgeListInterceptions(ctx,tc.filter)
340365
require.NoError(t,err)
341366
// We just compare UUID strings for the sake of this test.
@@ -354,10 +379,14 @@ func TestAIBridgeListInterceptions(t *testing.T) {
354379

355380
t.Run("FilterErrors",func(t*testing.T) {
356381
t.Parallel()
357-
client:=coderdtest.New(t,&coderdtest.Options{})
358-
_=coderdtest.CreateFirstUser(t,client)
382+
dv:=coderdtest.DeploymentValues(t)
383+
dv.Experiments= []string{string(codersdk.ExperimentAIBridge)}
384+
client,_:=coderdenttest.New(t,&coderdenttest.Options{
385+
Options:&coderdtest.Options{
386+
DeploymentValues:dv,
387+
},
388+
})
359389
experimentalClient:=codersdk.NewExperimentalClient(client)
360-
ctx:=testutil.Context(t,testutil.WaitLong)
361390

362391
// No need to insert any test data, we're just testing the filter
363392
// errors.
@@ -413,6 +442,7 @@ func TestAIBridgeListInterceptions(t *testing.T) {
413442
for_,tc:=rangecases {
414443
t.Run(tc.name,func(t*testing.T) {
415444
t.Parallel()
445+
ctx:=testutil.Context(t,testutil.WaitLong)
416446
res,err:=experimentalClient.AIBridgeListInterceptions(ctx, codersdk.AIBridgeListInterceptionsFilter{
417447
FilterQuery:tc.q,
418448
})

‎enterprise/coderd/aibridged.go‎

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,13 @@ import (
66
"io"
77
"net/http"
88

9-
"github.com/go-chi/chi/v5"
109
"golang.org/x/xerrors"
1110
"storj.io/drpc/drpcmux"
1211
"storj.io/drpc/drpcserver"
1312

1413
"cdr.dev/slog"
1514

16-
"github.com/coder/coder/v2/coderd/httpmw"
1715
"github.com/coder/coder/v2/coderd/tracing"
18-
"github.com/coder/coder/v2/codersdk"
1916
"github.com/coder/coder/v2/codersdk/drpcsdk"
2017
"github.com/coder/coder/v2/enterprise/x/aibridged"
2118
aibridgedproto"github.com/coder/coder/v2/enterprise/x/aibridged/proto"
@@ -25,24 +22,12 @@ import (
2522
// RegisterInMemoryAIBridgedHTTPHandler mounts [aibridged.Server]'s HTTP router onto
2623
// [API]'s router, so that requests to aibridged will be relayed from Coder's API server
2724
// to the in-memory aibridged.
28-
func (api*API)RegisterInMemoryAIBridgedHTTPHandler(srv*aibridged.Server) {
25+
func (api*API)RegisterInMemoryAIBridgedHTTPHandler(srvhttp.Handler) {
2926
ifsrv==nil {
3027
panic("aibridged cannot be nil")
3128
}
3229

33-
ifapi.AGPL.RootHandler==nil {
34-
panic("api.RootHandler cannot be nil")
35-
}
36-
37-
aibridgeEndpoint:="/api/experimental/aibridge"
38-
39-
r:=chi.NewRouter()
40-
r.Group(func(r chi.Router) {
41-
r.Use(httpmw.RequireExperiment(api.AGPL.Experiments,codersdk.ExperimentAIBridge))
42-
r.HandleFunc("/*",http.StripPrefix(aibridgeEndpoint,srv).ServeHTTP)
43-
})
44-
45-
api.AGPL.RootHandler.Mount(aibridgeEndpoint,r)
30+
api.aibridgedHandler=srv
4631
}
4732

4833
// CreateInMemoryAIBridgeServer creates a [aibridged.DRPCServer] and returns a

‎enterprise/coderd/coderd.go‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,30 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
226226
returnapi.refreshEntitlements(ctx)
227227
}
228228

229+
api.AGPL.ExperimentalHandler.Group(func(r chi.Router) {
230+
r.Route("/aibridge",func(r chi.Router) {
231+
r.Use(
232+
httpmw.RequireExperimentWithDevBypass(api.AGPL.Experiments,codersdk.ExperimentAIBridge),
233+
)
234+
r.Group(func(r chi.Router) {
235+
r.Use(apiKeyMiddleware)
236+
r.Get("/interceptions",api.aiBridgeListInterceptions)
237+
})
238+
239+
// This is a bit funky but since aibridge only exposes a HTTP
240+
// handler, this is how it has to be.
241+
r.HandleFunc("/*",func(rw http.ResponseWriter,r*http.Request) {
242+
ifapi.aibridgedHandler==nil {
243+
httpapi.Write(r.Context(),rw,http.StatusNotFound, codersdk.Response{
244+
Message:"aibridged handler not mounted",
245+
})
246+
return
247+
}
248+
api.aibridgedHandler.ServeHTTP(rw,r)
249+
})
250+
})
251+
})
252+
229253
api.AGPL.APIHandler.Group(func(r chi.Router) {
230254
r.Get("/entitlements",api.serveEntitlements)
231255
// /regions overrides the AGPL /regions endpoint
@@ -677,6 +701,8 @@ type API struct {
677701

678702
licenseMetricsCollector*license.MetricsCollector
679703
tailnetService*tailnet.ClientService
704+
705+
aibridgedHandler http.Handler
680706
}
681707

682708
// writeEntitlementWarningsHeader writes the entitlement warnings to the response header

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp