Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agentplane/action_service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ authoring package and its `resources` target remain at their existing path for c
system-test consumers.

The Go integration app obtains PolicySet names from the Policy Controller's
`ListPolicySetNames` gRPC API through [`AppService.GetSandboxForm`](../app/go/appconfigapi.go).
`ListPolicySetNames` gRPC API through [`AppService.GetSandboxForm`](../app/internal/server/appconfigapi.go).
Its effective action-policy view comes from the Action Service's generated `WatchActionPolicy`
response. The Python
`policies/resources` parser remains in cdk8s policy authoring and Python test support; Python Pydantic
Expand Down
8 changes: 4 additions & 4 deletions agentplane/app/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ py_proto_library_with_mypy_stubs(
genrule(
name = "openapi_schema",
outs = ["openapi.json"],
cmd = "$(location //agentplane/app/go:export_schema_bin) --export-openapi > $@",
tools = ["//agentplane/app/go:export_schema_bin"],
cmd = "$(location //agentplane/app/cmd:export_schema_bin) --export-openapi > $@",
tools = ["//agentplane/app/cmd:export_schema_bin"],
visibility = ["//agentplane/app/frontend:__pkg__"],
)

Expand Down Expand Up @@ -236,7 +236,7 @@ py_test(
# serving image.
pkg_tar(
name = "app_binary_layer",
srcs = ["//agentplane/app/go:agentplane-app"],
srcs = ["//agentplane/app/cmd:agentplane-app"],
mode = "0755",
package_dir = "/usr/local/bin",
)
Expand Down Expand Up @@ -653,7 +653,7 @@ py_library(
name = "integration_fixtures",
testonly = True,
srcs = ["integration_fixtures.py"],
data = ["//agentplane/app/go:agentplane-app"], # keep: subprocess fixture migration
data = ["//agentplane/app/cmd:agentplane-app"], # keep: subprocess fixture migration
deps = [
"//agentplane:subjects",
"//agentplane/app/testing:history",
Expand Down
11 changes: 6 additions & 5 deletions agentplane/app/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Agentplane integration app

The human-facing API is a Go service built from `//agentplane/app/go:agentplane-app` and packaged as
The human-facing API is a Go service built from `//agentplane/app/cmd:agentplane-app` and packaged as
`//agentplane/app:image`. It proxies Sandbox management through the Runner Gateway's
`EnvironmentService` with its Pod-bound service token, creates Sessions and submits commands through
the Session Dispatcher, and uses the Runner
Expand Down Expand Up @@ -86,16 +86,17 @@ get their Threads once it does.

## Implementation and testing

- `go/`: configuration, Huma REST routes, raw HTTP streams and the service lifecycle. The generated
frontend API comes from `//agentplane/app/go:export_schema_bin`.
- `internal/server/`: Huma REST routes, raw HTTP streams and service composition. The generated
frontend API comes from `//agentplane/app/cmd:export_schema_bin`.
- `cmd/`: process signal handling, CLI selection and the `agentplane-app` executable.
- `internal/threads/`: operator-owned Thread metadata. Generated Dispatcher HTTP routes own command submissions.
History owns event storage, folding and evidence; `internal/historydata/` reads it through gRPC.
- `internal/proxy/`: authenticated Electric entity/chunk forwarding with current History projection-epoch checks.
Native service RPCs use generated app-side HTTP gateways with request-bound credentials.
- `internal/auth/` and `internal/federation/`: PostgreSQL browser sessions, signed OIDC login and operator token
exchange. Logout, expiry and replica notifications end browser streams.
- `internal/migrations/` and `runtime.go`: embedded Goose schema and service startup. `runtime.go` uses
the shared `agentplane/postgres/migrate` lifecycle before opening the API.
- `internal/migrations/` and `internal/server/runtime.go`: embedded Goose schema and service startup.
The server uses the shared `agentplane/postgres/migrate` lifecycle before opening the API.
- `settings.py`, `presets.py`, `action_federation_settings.py`, `oidc.py` and
`sandbox_models.py`: deployment configuration schema used by cdk8s.
- `agentplane/sandboxes/runtimeconfig`: shared deployment-published model and harness offers read by
Expand Down
37 changes: 37 additions & 0 deletions agentplane/app/cmd/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")

package(default_visibility = [
"//agentplane/app:__pkg__",
"//agentplane/app:__subpackages__",
])

go_library(
name = "cmd_lib",
srcs = ["main.go"],
importpath = "github.com/agentydragon/ducktape/agentplane/app/cmd",
deps = [
"//agentplane/app/internal/migrations",
"//agentplane/app/internal/server",
"//agentplane/app/internal/settings",
"//agentplane/postgres/migrate",
"@com_github_go_logr_logr//:logr",
"@io_k8s_sigs_controller_runtime//pkg/log",
],
)

go_binary(
name = "agentplane-app",
embed = [":cmd_lib"],
pure = "on",
visibility = ["//agentplane:__subpackages__"],
)

go_binary(
name = "export_schema_bin",
embed = [":cmd_lib"],
pure = "on",
visibility = [
"//agentplane/app:__pkg__",
"//agentplane/app:__subpackages__",
],
)
5 changes: 3 additions & 2 deletions agentplane/app/go/main.go → agentplane/app/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"syscall"

"github.com/agentydragon/ducktape/agentplane/app/internal/migrations"
"github.com/agentydragon/ducktape/agentplane/app/internal/server"
"github.com/agentydragon/ducktape/agentplane/app/internal/settings"
dbmigrate "github.com/agentydragon/ducktape/agentplane/postgres/migrate"
"github.com/go-logr/logr"
Expand All @@ -18,7 +19,7 @@ import (
func main() {
configureLogLevels(nil)
if len(os.Args) == 2 && os.Args[1] == "--export-openapi" {
if err := exportOpenAPI(os.Stdout); err != nil {
if err := server.ExportOpenAPI(os.Stdout); err != nil {
slog.Error("export Agentplane OpenAPI schema", "error", err)
os.Exit(1)
}
Expand All @@ -43,7 +44,7 @@ func main() {
os.Exit(1)
}
configureLogLevels(config.LogLevels)
if err := run(ctx, config); err != nil && ctx.Err() == nil {
if err := server.Run(ctx, config); err != nil && ctx.Err() == nil {
slog.Error("Agentplane app stopped", "error", err)
os.Exit(1)
}
Expand Down
2 changes: 1 addition & 1 deletion agentplane/app/frontend/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ client can leave bodies past a size to be read when shown, and a memory budget a
## System page probes

The System page does not probe the Kubernetes API, whose reachability the app has but does not probe
(the live views show only the watch's freshness). Consider a Kubernetes API probe beside the others in `app/go/runtime.go` if an
(the live views show only the watch's freshness). Consider a Kubernetes API probe beside the others in `app/internal/server/runtime.go` if an
operator wants to see it there.
2 changes: 1 addition & 1 deletion agentplane/app/integration_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def app_database_template(postgres_admin_url: str) -> Iterator[PostgresDatabaseT
with PostgresDatabaseTemplate(postgres_admin_url, "agentplane_app_test_template") as template:
migrated = subprocess.run(
[
(Runfiles.CreateOrRaise().root() / "ducktape/agentplane/app/go/agentplane-app_/agentplane-app"),
(Runfiles.CreateOrRaise().root() / "ducktape/agentplane/app/cmd/agentplane-app_/agentplane-app"),
"--migrate-only",
],
env={
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")

package(default_visibility = ["//agentplane/app:__subpackages__"])

go_library(
name = "main_lib",
name = "server",
srcs = [
"appconfigapi.go",
"appservice.go",
"main.go",
"operatorapi.go",
"runnerapi.go",
"runtime.go",
Expand All @@ -20,7 +19,7 @@ go_library(
"threadreadapi.go",
"trace_relay.go",
],
importpath = "github.com/agentydragon/ducktape/agentplane/app/go",
importpath = "github.com/agentydragon/ducktape/agentplane/app/internal/server",
deps = [
"//agentplane/action_service/api/contracts:action_service_go_proto",
"//agentplane/action_service/api/contracts:linkage_service_go_proto",
Expand Down Expand Up @@ -61,7 +60,6 @@ go_library(
"//agentplane/sandboxes/runtimeconfig",
"@com_github_danielgtaylor_huma_v2//:huma",
"@com_github_danielgtaylor_huma_v2//adapters/humago",
"@com_github_go_logr_logr//:logr",
"@com_github_google_uuid//:uuid",
"@com_github_grpc_ecosystem_grpc_gateway_v2//runtime",
"@com_github_lib_pq//:pq",
Expand All @@ -70,7 +68,6 @@ go_library(
"@io_k8s_apimachinery//pkg/apis/meta/v1:meta",
"@io_k8s_apimachinery//pkg/types",
"@io_k8s_client_go//kubernetes",
"@io_k8s_sigs_controller_runtime//pkg/log",
"@io_k8s_utils//ptr",
"@org_golang_google_genproto_googleapis_rpc//errdetails",
"@org_golang_google_grpc//:grpc",
Expand All @@ -89,37 +86,23 @@ go_library(
],
)

go_binary(
name = "agentplane-app",
embed = [":main_lib"],
pure = "on",
visibility = ["//agentplane:__subpackages__"],
)

go_binary(
name = "export_schema_bin",
embed = [":main_lib"],
pure = "on",
visibility = ["//agentplane/app:__subpackages__"],
)

go_test(
name = "server_test",
srcs = ["server_test.go"],
embed = [":main_lib"],
embed = [":server"],
deps = ["//agentplane/app/internal/auth"],
)

go_test(
name = "trace_relay_test",
srcs = ["trace_relay_test.go"],
embed = [":main_lib"],
embed = [":server"],
)

go_test(
name = "action_facade_test",
srcs = ["action_facade_test.go"],
embed = [":main_lib"],
embed = [":server"],
deps = [
"//agentplane/action_service/api/contracts:action_service_go_proto",
"//agentplane/action_service/api/contracts:operator_action_service_go_proto",
Expand All @@ -142,7 +125,7 @@ go_test(
go_test(
name = "policy_facade_test",
srcs = ["policy_facade_test.go"],
embed = [":main_lib"],
embed = [":server"],
deps = [
"//agentplane/app/internal/proxy",
"//agentplane/egress/api/admin:egress_admin_go_proto",
Expand All @@ -161,13 +144,13 @@ go_test(
go_test(
name = "schema_export_test",
srcs = ["schema_export_test.go"],
embed = [":main_lib"],
embed = [":server"],
)

go_test(
name = "runnerapi_test",
srcs = ["runnerapi_test.go"],
embed = [":main_lib"],
embed = [":server"],
deps = [
"//agentplane/app/internal/auth",
"//agentplane/proto:session_go_proto",
Expand All @@ -181,7 +164,7 @@ go_test(
go_test(
name = "appconfigapi_test",
srcs = ["appconfigapi_test.go"],
embed = [":main_lib"],
embed = [":server"],
deps = [
"//agentplane/app/internal/auth",
"//agentplane/app/internal/settings",
Expand All @@ -194,7 +177,7 @@ go_test(
go_test(
name = "statusapi_test",
srcs = ["statusapi_test.go"],
embed = [":main_lib"],
embed = [":server"],
deps = [
"//agentplane/app/internal/auth",
"//agentplane/app/internal/status",
Expand All @@ -206,7 +189,7 @@ go_test(
go_test(
name = "policyapi_test",
srcs = ["policyapi_test.go"],
embed = [":main_lib"],
embed = [":server"],
deps = [
"@io_k8s_api//authentication/v1:authentication",
"@io_k8s_apimachinery//pkg/apis/meta/v1:meta",
Expand All @@ -216,7 +199,7 @@ go_test(
go_test(
name = "sessionapi_test",
srcs = ["sessionapi_test.go"],
embed = [":main_lib"],
embed = [":server"],
deps = [
"//agentplane/app:app_service_go_proto",
"//agentplane/app/internal/auth",
Expand Down Expand Up @@ -250,7 +233,7 @@ go_test(
go_test(
name = "operatorapi_test",
srcs = ["operatorapi_test.go"],
embed = [":main_lib"],
embed = [":server"],
deps = [
"//agentplane/action_service/api/contracts:linkage_service_go_proto",
"//agentplane/app/internal/auth",
Expand All @@ -271,7 +254,7 @@ go_test(
go_test(
name = "threadreadapi_test",
srcs = ["threadreadapi_test.go"],
embed = [":main_lib"],
embed = [":server"],
deps = [
"//agentplane/app:app_service_go_proto",
"//agentplane/app/internal/auth",
Expand All @@ -294,7 +277,7 @@ go_test(
go_test(
name = "streamapi_test",
srcs = ["streamapi_test.go"],
embed = [":main_lib"],
embed = [":server"],
deps = [
"//agentplane/app/internal/auth",
"//agentplane/app/internal/proxy",
Expand Down Expand Up @@ -327,8 +310,8 @@ go_test(
name = "staging_config_test",
srcs = ["staging_config_test.go"],
data = ["//cluster/k8s/agentplane-staging:agentplane-staging.k8s.yaml"],
embed = [":main_lib"],
x_defs = {"github.com/agentydragon/ducktape/agentplane/app/go.stagingConfigRlocation": "$(rlocationpath //cluster/k8s/agentplane-staging:agentplane-staging.k8s.yaml)"},
embed = [":server"],
x_defs = {"github.com/agentydragon/ducktape/agentplane/app/internal/server.stagingConfigRlocation": "$(rlocationpath //cluster/k8s/agentplane-staging:agentplane-staging.k8s.yaml)"},
deps = [
"//agentplane/app/internal/settings",
"@in_gopkg_yaml_v3//:yaml_v3",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package server

import (
"context"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package server

import (
"context"
Expand All @@ -19,10 +19,10 @@ type policySetNameReader interface {
ListPolicySetNames(context.Context, *policypb.ListPolicySetNamesRequest, ...grpc.CallOption) (*policypb.ListPolicySetNamesResponse, error)
}

// RegisterAppConfigRoutes serves the app-owned browser configuration through generated
// registerAppConfigRoutes serves the app-owned browser configuration through generated
// ProtoJSON HTTP routes. The generated gateway and service implementation share this process;
// there is no separate config service or internal HTTP hop.
func RegisterAppConfigRoutes(server *HTTPServer, service *appService) error {
func registerAppConfigRoutes(server *httpServer, service *appService) error {
gateway := runtime.NewServeMux()
if err := apppb.RegisterAppServiceHandlerServer(context.Background(), gateway, service); err != nil {
return err
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package server

import (
"context"
Expand Down Expand Up @@ -53,9 +53,9 @@ func TestAppConfigRoutesUseGeneratedProtoJSONAndCallerAuthentication(t *testing.
},
NewSandboxDefaults: settings.NewSandboxDefaults{WakeOnSend: true, IdleSuspendAfterSeconds: appConfigInt64Pointer(900)},
}
server := NewHTTPServer(authentication)
server := newHTTPServer(authentication)
policySets := &appConfigPolicySetNames{names: []string{"alpha", "zeta"}}
if err := RegisterAppConfigRoutes(server, &appService{config: config, policySetNames: policySets}); err != nil {
if err := registerAppConfigRoutes(server, &appService{config: config, policySetNames: policySets}); err != nil {
t.Fatal(err)
}
handler := server.Handler(authentication)
Expand Down Expand Up @@ -141,9 +141,9 @@ func TestSandboxFormReturnsUnavailableWhenPolicyServiceFails(t *testing.T) {
if err != nil {
t.Fatal(err)
}
server := NewHTTPServer(authentication)
server := newHTTPServer(authentication)
policySets := &appConfigPolicySetNames{err: errors.New("policy backend unavailable")}
if err := RegisterAppConfigRoutes(server, &appService{policySetNames: policySets}); err != nil {
if err := registerAppConfigRoutes(server, &appService{policySetNames: policySets}); err != nil {
t.Fatal(err)
}
request := httptest.NewRequest(http.MethodGet, "/upstream/app-config/v1/sandbox-form", nil)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package main
package server

import (
apppb "github.com/agentydragon/ducktape/agentplane/app/appservicepb"
Expand Down
Loading
Loading