Documentation
¶
Overview ¶
Package cli — admin_bootstrap.go: ensure the admin endpoint has at least one valid bearer token at server boot (v2.3-3a task #28).
The first time the server comes up (admin_tokens table empty), we mint a system-owned superuser token, write the plaintext to `<datadir>/bootstrap_token` (mode 0600), and log a banner pointing at the file. Subsequent boots are a no-op — operators rotate the token via `agent-center admin token create / revoke`.
Why a file and not stdout: the operator launching the server may not even be the same user as the one who later runs `agent-center admin token list`; a file under datadir keeps the secret reachable across processes / sessions while still under the same uid.
Package cli — admin_client.go: HTTP-over-unix-socket Client that talks to the center process's admin endpoint.
Per conventions § 0.4 "AppService is the only entry": every CLI command outside the `server` boot path and a couple of schema-migration tools MUST round-trip through this Client rather than reach into the BC's Repositories / Services directly. The Client mirrors the admin endpoint surface registered in internal/admin/api/server.go (~79 methods grouped by BC).
Mirror of internal/workerdaemon/AdminClient (Phase C); we don't reuse that one because the CLI needs a much wider method surface and the worker-daemon transport intentionally exposes only the 5 methods the daemon itself needs.
Sub-files by BC:
- admin_client_workforce.go (workers, proposals, agents, projects)
- admin_client_conversation.go (conv/msg/channel/participant/derivation)
- admin_client_taskruntime.go (task/exec/IR/artifact/dispatch/kill)
- admin_client_discussion.go (issue lifecycle + bind/link)
- admin_client_secret.go (user_secret CRUD)
- admin_client_identity.go (identity register / find)
- admin_client_observability.go (query / inspect / fleet / stats / logs)
- admin_client_cognition.go (supervisor spawn / invocation / decision)
All sub-files share the doJSON / doPOST / doGET helpers defined here.
Package cli — admin_client_admintoken.go: Client methods for the AdminToken management surface (v2.3-3a task #28). Mirrors internal/admin/api/admintoken.go 1:1.
Package cli — admin_client_conversation.go: Client methods for the Conversation BC admin surface (ConvRepo / MsgRepo / MessageWriter / ChannelMgmtSvc / ParticipantMgmtSvc / CarryOverSvc / ConvRefRepo). Mirrors internal/admin/api/conversation.go 1:1.
19 endpoints registered in internal/admin/api/server.go under the `/admin/conversation/` prefix. Naming: methods on Client are named <Resource><Verb> to match the admin route segments (e.g. `ChannelCreate` for `POST /admin/conversation/channel/create`). Read methods return typed DTO structs whose JSON tags match the JSON keys emitted by the admin endpoint's projection helpers (convMap, messageMap, refsToMap) exactly.
v2.3-1 (task #24) closed the two prior v2.2 mismatches:
- `POST /admin/conversation/participant/leave` now exists → ParticipantLeave method below; `channel leave` CLI goes through Client uniformly (no more direct-service fallback).
- `GET /admin/conversation/msg/find-recent` now exists → MessageFindRecent method below; `conversation read --tail=N` and `conversation tail` no longer trim client-side off the 200-cap find-by-conversation-id helper.
Package cli — admin_client_observability.go: Client methods for the Observability BC admin surface (event find / query / inspect / fleet / stats / logs). Mirrors internal/admin/api/observability.go 1:1.
Logs/Open is special: the admin endpoint streams the gzipped blob body as `Content-Type: application/gzip` with the blob ref in `X-Blob-Ref`. The Client returns the raw body bytes (gzip-compressed) and the ref; handlers stream those bytes to stdout the same way the pre-refactor LogsSvc.Open path did.
Package cli — admin_client_secret.go: Client methods for the SecretManagement BC admin surface (user_secret CRUD + Resolve). Mirrors internal/admin/api/secret.go 1:1.
SecretResolve is v2.3-3b (task #29) and gated server-side by the `secret:resolve` scope. CLI tokens generally don't carry this scope — the method is here for test parity with the worker-daemon AdminClient (and so any future CLI command like `secret reveal` can plug in).
Package cli — admin_client_testhelper.go: test scaffolding that spins up an in-process admin endpoint and returns a Client pointing at it.
Use this in CLI handler tests instead of the legacy newTestApp() path (which wires Services directly on the App). v2.2 Phase B per docs/plans/v2.2-audits/v22-B-cli-refactor-audit.md: handlers must route through Client, not the Service fields.
Usage:
app, cleanup := setupAdminServerForTests(t) defer cleanup() // app.Client is wired; app.DB / app.WorkerRepo / ... are also // populated because the helper builds a full App + serves it.
The helper is exported (lowercase but referenced from _test.go files in this same package) and lives in a non-test file so it can be referenced from package-level documentation/examples. It compiles into the production binary as dead code — harmless because the listener never starts until the helper is called.
Package cli — admin_client_workforce.go: Client methods for the Workforce BC admin surface (workers, proposals, projects). Mirrors internal/admin/api/workforce.go 1:1.
Naming: methods on Client are named <Resource><Verb> to match the admin route segments (e.g. `WorkerEnroll` for `POST /admin/workforce/worker/enroll`). Read methods return typed DTO structs whose JSON tags match the JSON keys emitted by the admin endpoint's projection helpers (`workerMap`, `proposalMap`, etc.).
handlers_install.go — `agent-center install` subcommand family. v2.4-D-A1 (task #35): skeleton + version detection + branch routing. A2 (task #36) implements the systemd / launchd install path; A5 (#39) implements the upgrade flow. A1 ships:
- `agent-center install center [--prefix=...] [--user-mode]` — installs server on local machine (host A).
- `agent-center install worker --bootstrap=... --token=... [...]` — installs worker daemon on local machine (host B).
Both commands detect existing installs and branch:
- **Fresh**: no prior install at prefix → A2 will write binaries, units, start service.
- **SameVersion**: install dir for this exact version already exists → idempotent no-op, exit 0 with "already installed" message.
- **Upgrade**: different version exists → A5 will atomic-swap symlink + restart service + rollback on failure.
A1 implements the routing + clear error messages. The real install / upgrade work is stubbed (returns "not implemented in A1; coming in A2/A5") so the CLI shape is observable + testable before the implementation lands.
handlers_list_centers.go — `agent-center list-local-centers` (v2.7.1 #211).
Lists every center deployment installed on this machine so an operator (or a Tester running multiple instances in parallel) can see, at a glance, which instances exist, where they live, their ports, whether they run as a managed service or foreground, and whether the web console is currently reachable. Discovery is filesystem-based: it scans the install parent dir for `<base>` (the default instance) + `<base>.<instance>` prefixes that contain an etc/config.yaml.
handlers_list_workers.go — `agent-center list-local-workers` (v2.8 #170).
Symmetric to `list-local-centers` (#211): lists every worker deployment installed on this machine — both production workers (under the prod install parent, e.g. ~/.agent-center.<x>) and test-instance workers (under ~/.agent-center-test/<id>/worker-<n>), each tagged with its `namespace` (prod|test) so a single discovery surface serves both operators and the test-instance tooling (#255). Discovery is filesystem-based: a directory qualifies when it holds an etc/config.yaml that is a WORKER config (a `worker:` section / worker.db sqlite path, never a center's web_console).
handlers_test_instance.go — `agent-center install/uninstall/list test-instance` (v2.8 #255).
A one-command test/dev sandbox: spin up an isolated agent-center topology (1 center + N workers) under a namespace physically separate from the production install (`~/.agent-center-test/<id>/` vs `~/.agent-center`), with dynamically-allocated free ports (skipping :7000, macOS AirPlay #161) and per-instance launchd labels — so multiple sandboxes coexist and a Tester can drive UI/acceptance without hand-allocating ports or hand-editing config.
Design constraints (locked in #255 design):
- Reuse the REAL install codepath: install drives installCenterFresh / installWorkerFresh in-process, so the generated config is the real thing (incl. blob_store, #159) — never hand-rolled (constraint #1). This file only chooses the namespace/ports/labels and orchestrates.
- Workers auto-enroll on launchd start using the center's bootstrap token (scope=*) + pinned fingerprint — no org/user/seed needed. Tenant seeding (signin user, org/project/channel, --with-agent) is the #257 follow-up.
- Cleanup is confined to the test namespace: uninstall only ever removes the `~/.agent-center-test/<id>/` subtree + the matching launchd labels, and `--id` is slug-validated so a caller cannot escape the root with `..` or an absolute path. The production `~/.agent-center` is never touched.
handlers_uninstall.go — `agent-center uninstall center|worker`.
v2.5.1 patch (#agent-center:5f6288e6, @oopslink ask msg=74fb3fa6). Inverts `install center|worker`: stop + unload the service unit, remove the install artefacts, leave the operator's data alone by default. `--purge` opts in to wiping `var/` + `logs/` and the install prefix itself.
Default-preserve rationale: var/ holds the sqlite database + master_key + worker-token + bootstrap_token — wiping those by accident is hard to undo. The expected reinstall-on-preserved-var path (uninstall → reinstall same prefix → existing data is reused; see ensureMasterKeyFile + sqlite Open auto-migration) is verified end-to-end in v2.5.1.
handlers_upgrade.go — `agent-center upgrade center|worker`.
v2.5.2 patch (@oopslink ask in #agent-center msg=8e5ea457). The upgrade path itself was already wired in v2.4-D-A5 (atomic symlink swap + health probe + auto-rollback under `install center` auto- detect); this file just exposes it as an explicit subcommand so operators can say "I want to upgrade" out loud instead of relying on the install handler's silent fresh-vs-upgrade branch.
Behaviour difference from `install center`:
- Fresh prefix → `install` walks the fresh path. `upgrade` rejects with "no existing install at <prefix>; run `install center` first".
- Same version → both walk the idempotent no-op path.
- Different ver → both walk the atomic-swap upgrade path.
install_errors.go — friendly error wrapping for `agent-center install` failure modes. v2.4-D-A6 (task #40). Covers the install-command- reachable subset of deployment doc § 5's 12-row failure matrix.
**Out of A6 scope** (visible at runtime, not at install time):
- "Cannot reach center at <host>:7300" — worker daemon's enroll attempt logs this to stderr after install completes
- "Token already used" / "Token expired" / "fingerprint mismatch" / "worker name already enrolled" — same: emerge from worker daemon first enroll attempt
- "DB migration failed" — server boot path; A5 health probe surfaces it via /admin/health timeout → rollback
**In A6 scope** (install-command-detectable):
- "Port already in use" — pre-flight TCP bind on the configured web port + admin TCP port (if set)
- "Need sudo" — wraps EACCES from systemd unit write with the friendly text suggesting `sudo` or `--user-mode`
- "Disk full" — wraps ENOSPC from binary copy with the friendly "free up space" hint
- "Same version already installed" — A1 already handles via state detection; this file adds the friendly recovery hint
install_fs.go — filesystem + service activation for `install center` / `install worker`. v2.4-D-A2 (task #36).
Responsibility split:
- A2 (this file): write versioned binaries + service unit + config + atomic symlink swap (current → versions/<v>); activate service.
- A5 (next ST): wrap the same flow with upgrade semantics — DB migration apply + service restart + health probe + auto-rollback.
On install success we print the operator-facing summary + URL + (for center) the bootstrap token. The version selection is the running binary's own version (installerVersion()).
install_platform.go — generate systemd unit (Linux) / launchd plist (Mac) for the center + worker services. v2.4-D-A2 (task #36).
Mac launchd path is the only one that must actually work for v2.4 PM acceptance (mac arm64 only per @oopslink 2026-05-26 scope narrow); systemd path is implemented + has unit tests for the unit-file rendering but is not validated end-to-end. Marked clearly so future iterations can validate on Linux without re-deriving the layout.
install_upgrade.go — atomic version-swap upgrade for `install center` and `install worker`. v2.4-D-A5 (task #39).
Sequence on `agent-center install center|worker` when an existing install is detected at a different version:
- Read `<prefix>/current` to capture the rollback target.
- Copy new-version binaries into `<prefix>/versions/<newver>/`.
- Write VERSION file.
- Atomic symlink swap `<prefix>/current` → `<prefix>/versions/<newver>`. (Service unit + config file unchanged — they point at `<prefix>/current/...` which is now the new version.)
- Restart the service via systemctl/launchctl.
- Health probe: poll `/admin/health` over unix socket (center) or `<launchctl|systemctl> is-active` (worker) for up to 10s.
- On any failure between (4)-(6): swap symlink BACK to the rollback target + restart + return error.
Config + unit files are NOT rewritten on upgrade — preserves operator edits and matches the "same command does install + upgrade" UX. DB migration: the new server binary auto-runs migrations on startup via the existing migrate.Up() path; we don't pre-apply, just rely on the boot path + health probe to confirm the migration finished cleanly.
Package cli implements the agent-center CLI router + handler registry.
Per plan-1 § 3.1.4: stdlib `flag` + hand-rolled sub-command router (R8 spike decision). The router supports nested verbs (e.g. `worker proposal accept`) by recursively matching positional args against a static command tree.
test_instance_agent.go — `install test-instance --with-agent` (v2.8 #261).
Phase 2 of the test-instance tenant layer. Builds on --with-seed (#257): after seeding a usable tenant, it org-enrolls the workers INTO the seeded org (via the org-scoped mint-enroll flow, using the owner's session) so they control-connect — resolving the #255 finding where admin-endpoint-enrolled workers stay workforce-registered but control-disconnect with 409 worker_not_org_enrolled. It then creates a real agent bound to a connected worker and dispatches a simple task so the agent runs and produces real tool_use/result events (closing the v2.7.1 #216 / §8 caveat source).
REORDER vs #255: workers are installed HERE (after the seed), with org-bound enroll tokens — not during provisionTestInstance (which, for --with-agent, installs the center alone). All driving is via the REAL center HTTP API.
test_instance_seed.go — `install test-instance --with-seed` (v2.8 #257).
After the test sandbox's center is healthy, drive a usable tenant through the REAL center HTTP API (the same endpoints a human/agent uses — never a SQL shortcut): signup (creates the owner user + org + auto-signin JWT) → create one project → create one channel. The resulting signin credentials + entity ids are folded into the access pack so a consumer can log into the UI and navigate entities with zero round-trips (closes the manual-seed handoff pain that every acceptance round hit).
Scope (#257 phase 1): tenant seed only. Worker org-enrollment + `--with-agent` (real agent producing tool events on a control-connected worker) is phase 2 — the #255 workers remain workforce-registered but not org-connected until then (see the access pack's workers_note).
Index ¶
- Constants
- Variables
- func EnsureBootstrapToken(ctx context.Context, app *App, datadir string, logger func(string)) error
- func EnsureSocketExists(c *Client) error
- func FormatJSONError(reason, message string) string
- func GlobalConfigPath() string
- func IsClientNotConfigured(err error) bool
- func IsServerUnreachable(err error) bool
- func IsValidFormat(in string) bool
- func NormalizeFormat(in string) (string, bool)
- func OpenAndMigrate(cfg config.Config) (*sql.DB, error)
- func ParseFormat(v string) string
- func ResolvedBuildBranch() string
- func ResolvedBuildBuiltAt() string
- func ResolvedBuildCommit() string
- func ResolvedBuildVersion() string
- func SetGlobalConfigPath(p string)
- func SetInstallBuildBranch(b string)
- func SetInstallBuildBuiltAt(t string)
- func SetInstallBuildCommit(c string)
- func SetInstallBuildVersion(v string)
- func StripGlobalFlags(args []string, cfgPath string) []string
- type AdminTokenCreateRequest
- type AdminTokenCreateResponse
- type AdminTokenDTO
- type AdminTokenRevokeRequest
- type AdminTransportConfig
- type AdminTransportInfo
- type App
- type ChannelArchiveRequest
- type ChannelCreateRequest
- type ChannelCreateResponse
- type Client
- func (c *Client) AdminTokenCreate(ctx context.Context, req AdminTokenCreateRequest) (AdminTokenCreateResponse, error)
- func (c *Client) AdminTokenList(ctx context.Context) ([]AdminTokenDTO, error)
- func (c *Client) AdminTokenRevoke(ctx context.Context, req AdminTokenRevokeRequest) error
- func (c *Client) CarryOverFindByChildConv(ctx context.Context, childConvID string) ([]ConversationMessageReferenceDTO, error)
- func (c *Client) CarryOverFindBySourceMsg(ctx context.Context, sourceMsgID string) ([]ConversationMessageReferenceDTO, error)
- func (c *Client) ChannelArchive(ctx context.Context, req ChannelArchiveRequest) (EventIDResponse, error)
- func (c *Client) ChannelCreate(ctx context.Context, req ChannelCreateRequest) (ChannelCreateResponse, error)
- func (c *Client) CollaborationEffectEvidence(ctx context.Context, effectID, projectID string) (collaborationeffect.EvidenceResult, error)
- func (c *Client) CollaborationEffectsQuery(ctx context.Context, filter collaborationeffect.Filter) (collaborationeffect.QueryResult, error)
- func (c *Client) ConvRefFindByChildConvID(ctx context.Context, childConvID string) ([]ConversationMessageReferenceDTO, error)
- func (c *Client) ConvRefFindBySourceMsgID(ctx context.Context, sourceMsgID string) ([]ConversationMessageReferenceDTO, error)
- func (c *Client) ConversationArchive(ctx context.Context, req ConversationArchiveRequest) (EventIDResponse, error)
- func (c *Client) ConversationClose(ctx context.Context, req ConversationCloseRequest) (EventIDResponse, error)
- func (c *Client) ConversationFind(ctx context.Context, kind, status string) ([]ConversationDTO, error)
- func (c *Client) ConversationFindByID(ctx context.Context, id string) (ConversationDTO, error)
- func (c *Client) ConversationFindByName(ctx context.Context, name string) (ConversationDTO, error)
- func (c *Client) ConversationOpen(ctx context.Context, req ConversationOpenRequest) (ConversationOpenResponse, error)
- func (c *Client) EventFind(ctx context.Context, filter EventFindFilter) ([]EventDTO, error)
- func (c *Client) EventFindByID(ctx context.Context, id string) (EventDTO, error)
- func (c *Client) FleetSnapshotRaw(ctx context.Context, projectID string, out any) error
- func (c *Client) InspectRaw(ctx context.Context, kind, id string, out any) error
- func (c *Client) LogsOpen(ctx context.Context, kind, id string) ([]byte, string, error)
- func (c *Client) MessageAppend(ctx context.Context, req MsgAppendRequest) (MsgAppendResponse, error)
- func (c *Client) MessageFindByConversationID(ctx context.Context, convID string) ([]MessageDTO, error)
- func (c *Client) MessageFindByID(ctx context.Context, id string) (MessageDTO, error)
- func (c *Client) MessageFindRecent(ctx context.Context, convID string, n int) ([]MessageDTO, error)
- func (c *Client) ParticipantInvite(ctx context.Context, req ParticipantInviteRequest) (EventIDResponse, error)
- func (c *Client) ParticipantKick(ctx context.Context, req ParticipantKickRequest) (EventIDResponse, error)
- func (c *Client) ParticipantLeave(ctx context.Context, req ParticipantLeaveRequest) (EventIDResponse, error)
- func (c *Client) ProjectFindAll(ctx context.Context, _ string) ([]ProjectDTO, error)
- func (c *Client) ProjectFindByID(ctx context.Context, id string) (ProjectDTO, error)
- func (c *Client) QueryRaw(ctx context.Context, req QueryRequest, out any) error
- func (c *Client) SecretCreate(ctx context.Context, req SecretCreateRequest) (SecretCreateResponse, error)
- func (c *Client) SecretFindAll(ctx context.Context, kind, state string) ([]UserSecretDTO, error)
- func (c *Client) SecretFindByID(ctx context.Context, id string) (UserSecretDTO, error)
- func (c *Client) SecretFindByName(ctx context.Context, name string) (UserSecretDTO, error)
- func (c *Client) SecretResolve(ctx context.Context, name string) ([]byte, error)
- func (c *Client) SecretRevoke(ctx context.Context, req SecretRevokeRequest) (EventIDResponse, error)
- func (c *Client) SecretRotate(ctx context.Context, req SecretRotateRequest) (EventIDResponse, error)
- func (c *Client) SocketPath() string
- func (c *Client) StatsAggregateRaw(ctx context.Context, scope, since string, out any) error
- func (c *Client) Token() string
- func (c *Client) WithToken(t string) *Client
- func (c *Client) WorkerEnroll(ctx context.Context, req WorkerEnrollRequest) (WorkerEnrollResponse, error)
- func (c *Client) WorkerFindAll(ctx context.Context) ([]WorkerDTO, error)
- func (c *Client) WorkerFindByID(ctx context.Context, id string) (WorkerDTO, error)
- func (c *Client) WorkerFindByStatus(ctx context.Context, status string) ([]WorkerDTO, error)
- type ClientError
- type Command
- func AdminBlobMigratePlaceholder() *Command
- func AgentRuntimeCommand() *Command
- func AgentSupervisorCommand() *Command
- func BootstrapCommand() *Command
- func ExecutorCommand() *Command
- func InstallCenterCommand() *Command
- func InstallCommand() *Command
- func InstallTestInstanceCommand() *Command
- func InstallWorkerCommand() *Command
- func ListLocalCentersCommand() *Command
- func ListLocalWorkersCommand() *Command
- func ListTestInstancesCommand() *Command
- func MCPHostCommand() *Command
- func MigrateGroupCommand() *Command
- func MigrateOrphanConditionsCommand() *Command
- func MigrateUpCommand() *Command
- func MigrateV1ToV2Command() *Command
- func ServerCommand() *Command
- func SystemCommands(buildVersion, buildCommit string) []*Command
- func UninstallCenterCommand() *Command
- func UninstallCommand() *Command
- func UninstallTestInstanceCommand() *Command
- func UninstallWorkerCommand() *Command
- func UpgradeCenterCommand() *Command
- func UpgradeCommand() *Command
- func UpgradeWorkerCommand() *Command
- func WorkerRecoverDeliveryCommand() *Command
- func WorkerRunCommand() *Command
- func WorkerShimPlaceholder() *Command
- type ConversationArchiveRequest
- type ConversationCloseRequest
- type ConversationDTO
- type ConversationMessageReferenceDTO
- type ConversationOpenRequest
- type ConversationOpenResponse
- type ErrorReason
- type EventDTO
- type EventFindFilter
- type EventIDResponse
- type ExitCode
- type Handler
- type InstallState
- type MessageDTO
- type MsgAppendRequest
- type MsgAppendResponse
- type ParticipantDTO
- type ParticipantInviteRequest
- type ParticipantKickRequest
- type ParticipantLeaveRequest
- type ProjectDTO
- type QueryRequest
- type Router
- type SecretCreateRequest
- type SecretCreateResponse
- type SecretResolveResponse
- type SecretRevokeRequest
- type SecretRotateRequest
- type UserSecretDTO
- type WebConsoleEnrollWiring
- type WorkerDTO
- type WorkerEnrollRequest
- type WorkerEnrollResponse
- type WriterAlias
Constants ¶
const ( FormatTable = "table" FormatJSON = "json" FormatText = "text" FormatHuman = "human" // alias of FormatTable; not advertised. )
Output format constants. P11 § 3.8: the CLI exposes three formats — `table` (default, human-readable), `json` (stable schema, snake_case keys; safe for scripting), and `text` (one canonical identifier per line; safe for `xargs`).
`human` is retained as a backwards-compatible alias of `table` so pre-§3.8 scripts that pass `--format=human` keep working. It is not advertised in help strings and `NormalizeFormat` collapses it onto `table`.
const ( ExitOK = 0 ExitBusinessError = 1 ExitUsage = 2 ExitVersionConflict = 16 ExitNotFound = 17 ExitInvalidTransition = 18 ExitInvariantViolation = 19 ExitNotImplemented = 64 ExitSIGINT = 130 )
Exit codes per 03-cli § 5.
const BootstrapTokenFilename = "bootstrap_token"
BootstrapTokenFilename is the on-disk name of the bootstrap token file (joined with the resolved datadir).
const DefaultInstance = "default"
DefaultInstance is the singleton / back-compat center deployment name (v2.7.1 #211). `install center` with no --instance = this; it keeps the legacy prefix (~/.agent-center) + launchd label (com.agent-center.center) so existing operators are unaffected.
Variables ¶
var ErrClientNotConfigured = errors.New("admin client: not configured " +
"(server.admin_socket_path missing or server not running)")
ErrClientNotConfigured is returned from Client methods when the Client wasn't constructed (e.g. CLI invoked without an admin socket configured).
var ErrServerUnreachable = errors.New("admin server unreachable")
ErrServerUnreachable is wrapped around network errors that indicate the admin socket isn't accepting connections. Handlers translate this into a user-facing "is the server running?" hint.
Functions ¶
func EnsureBootstrapToken ¶
EnsureBootstrapToken mints a system token + writes plaintext to disk iff the admin_tokens table is currently empty.
datadir may be empty — in that case we fall back to filepath.Dir of the configured sqlite path (cfg.Server.SqlitePath). logger is the boot-banner writer (typically a fmt.Fprintf wrapper on stderr).
Returns nil on success or when bootstrap is unnecessary (table non-empty). Failure to write the file is fatal — the operator MUST have a way to authenticate, and silently swallowing the error would produce a deployment where the admin endpoint exists but nobody can reach it.
func EnsureSocketExists ¶
EnsureSocketExists is a courtesy preflight: if the configured socket doesn't exist on disk, return a friendly error pointing at how to start the server. Network-level failures (connect refused after the socket exists) surface as ErrServerUnreachable during the first call.
Returns nil when the socket file is present OR when c is nil (handlers that can run without the client should be unaffected).
func FormatJSONError ¶
FormatJSONError renders an error response.
func GlobalConfigPath ¶
func GlobalConfigPath() string
GlobalConfigPath returns the resolved config path published by BuildRouter (--config flag or AGENT_CENTER_CONFIG env). Empty when neither is set.
func IsClientNotConfigured ¶
IsClientNotConfigured reports whether err signals an absent Client.
func IsServerUnreachable ¶
IsServerUnreachable reports whether err looks like the server isn't accepting connections (socket missing, ECONNREFUSED, etc.).
func IsValidFormat ¶
IsValidFormat reports whether the input is an accepted format string.
func NormalizeFormat ¶
NormalizeFormat maps an input format string to one of the three canonical values. Empty input defaults to `table`. `human` aliases to `table`. Returns ok=false when the input is unrecognised.
func OpenAndMigrate ¶
OpenAndMigrate is a convenience that opens the DB pointed to by cfg and runs migrations. The caller is responsible for closing the DB.
func ParseFormat ¶
ParseFormat returns "human" or "json" (or yaml in the future); defaults to "human" for empty input.
func ResolvedBuildBranch ¶
func ResolvedBuildBranch() string
ResolvedBuildBranch returns the linker-injected branch, or "unknown".
func ResolvedBuildBuiltAt ¶
func ResolvedBuildBuiltAt() string
ResolvedBuildBuiltAt returns the linker-injected build timestamp, or "unknown".
func ResolvedBuildCommit ¶
func ResolvedBuildCommit() string
ResolvedBuildCommit returns the linker-injected commit (the same value the install command uses via installerCommit), exported so server-side surfaces (e.g. /api/system/version) can echo it. Falls back to "unknown".
func ResolvedBuildVersion ¶
func ResolvedBuildVersion() string
ResolvedBuildVersion returns the linker-injected version string if main() called SetInstallBuildVersion, otherwise "dev". Mirrors installerVersion() but exported so other server-side surfaces (e.g. /api/health) can echo the same value the install command printed. v2.4-D-X1 fix B10.
func SetGlobalConfigPath ¶
func SetGlobalConfigPath(p string)
SetGlobalConfigPath is called by BuildRouter to publish the global --config flag value to the system command handlers.
func SetInstallBuildBranch ¶
func SetInstallBuildBranch(b string)
SetInstallBuildBranch threads main.buildBranch from the binary's main(). No-op for the empty/"unknown" sentinel so `go run` stays branch-agnostic.
func SetInstallBuildBuiltAt ¶
func SetInstallBuildBuiltAt(t string)
SetInstallBuildBuiltAt threads main.buildBuiltAt from the binary's main().
func SetInstallBuildCommit ¶
func SetInstallBuildCommit(c string)
SetInstallBuildCommit threads main.buildCommit into the install command (v2.7.1 #234). No-ops for the "unknown" sentinel so `go run` stays commit-agnostic. Tests mutate installBuildCommit directly with a restore-on-defer pattern.
func SetInstallBuildVersion ¶
func SetInstallBuildVersion(v string)
SetInstallBuildVersion lets the binary's main() thread the linker- injected buildVersion into the install command. Called only when buildVersion is non-empty and not the "dev" sentinel; the empty case stays "dev" for `go run` / unversioned builds. Tests don't call this — they mutate installBuildVersion directly with a restore-on-defer pattern.
func StripGlobalFlags ¶
StripGlobalFlags removes the global --config / -c flags from args because they're handled out-of-band by BuildRouter.
Types ¶
type AdminTokenCreateRequest ¶
type AdminTokenCreateRequest struct {
Owner string `json:"owner"`
Scopes []string `json:"scopes"`
CreatedBy string `json:"created_by"`
}
AdminTokenCreateRequest is the body for /admin/admintoken/create.
type AdminTokenCreateResponse ¶
AdminTokenCreateResponse is the success body — id + plaintext. The plaintext is the operator's only chance to see the bearer; the server never echoes it again.
type AdminTokenDTO ¶
type AdminTokenDTO struct {
ID string `json:"id"`
Owner string `json:"owner"`
Scopes []string `json:"scopes"`
CreatedAt string `json:"created_at"`
CreatedBy string `json:"created_by"`
Version int `json:"version"`
RevokedAt string `json:"revoked_at,omitempty"`
RevokedBy string `json:"revoked_by,omitempty"`
RevokedReason string `json:"revoked_reason,omitempty"`
LastUsedAt string `json:"last_used_at,omitempty"`
}
AdminTokenDTO mirrors the JSON envelope returned by list/show. It intentionally omits plaintext + value_hash per ADR-aligned policy.
type AdminTokenRevokeRequest ¶
AdminTokenRevokeRequest is the body for /admin/admintoken/revoke.
type AdminTransportConfig ¶
type AdminTransportConfig struct {
SocketPath string
TCPListenAddr string
TLSCertPath string
TLSKeyPath string
FingerprintPath string
Hostname string
}
AdminTransportConfig captures the v2.3-7a (task #27) admin listener configuration: optional unix socket + optional TCP+TLS address with auto-managed cert + fingerprint files. At least one of SocketPath or TCPListenAddr must be non-empty.
type AdminTransportInfo ¶
type AdminTransportInfo struct {
TLSFingerprint string
TLSCertNotAfter time.Time
TLSCertGenerated bool
TLSExpiryWarn bool
TLSExpiryDays int
}
AdminTransportInfo is what runAdminEndpoint returns to the caller (boot banner code in handlers_system.go uses this to print the cert fingerprint, expiry, etc.).
type App ¶
type App struct {
Config config.Config
// Client is the admin transport. Populated in CLI mode; may be nil
// in server mode (the server doesn't dial itself).
Client *Client
// DB / Clock / IDGen / Service / Repo fields below are wired only
// in server mode (NewApp). CLI mode (NewClientApp) leaves them nil.
DB *sql.DB
Clock clock.Clock
IDGen idgen.Generator
DBHealth *persistence.DBHealthMonitor
// RuntimeImportValidationKey signs AI Runtime Preview/Apply tokens. It is
// derived from the restart-stable server master key.
RuntimeImportValidationKey []byte
WorkerRepo workforce.WorkerRepository
// PMProjectRepo is the new-model (pm) project repo used by the
// operator-scoped CLI project READ handlers (list/show). v2.7 #131
// PR-3 — the LOCAL list path uses its operator-global ListAll.
PMProjectRepo pm.ProjectRepository
ConvRepo conversation.ConversationRepository
MsgRepo conversation.MessageRepository
EventRepo *obsqlite.EventRepo
Sink *observability.EventSink
Authorization *authorization.Service
// Usage BC (v2.15.0 I28/F2): usage_events + model_prices repos backing the
// report_usage agent-tool.
UsageEventRepo *usagesql.UsageEventRepo
ModelPriceRepo *usagesql.ModelPriceRepo
EnrollSvc *wfservice.WorkerEnrollService
// WorkerConfigSvc backs the operator per-CLI capability toggle (v2.7 #147).
WorkerConfigSvc *wfservice.WorkerConfigService
// v2.7 ProjectManager BC AppService facade (ADR-0046) — backs the nested
// /api/projects/{project_id}/... routes + produces the outbox events the
// server-runtime relay projects into Conversation/Agent.
PMService *pmservice.Service
// CodeRepoService is the v2.18.4 BE-1 workspace CodeRepo AppService (issue-f980c8de)
// — workspace Repos CRUD + encrypted credential storage + the merge-check resolver.
CodeRepoService *coderepservice.Service
// OrchService is the T768 orchestration engine AppService backing the 18 agent MCP
// graph/node/edge tools (admin-api HandlerDeps.OrchService). The SAME instance is
// injected into PMService for graph-backed plan dispatch.
OrchService *orch.Service
// LiveState is the per-agent live executor snapshot store (v2.19.0): the SAME
// instance is wired into the admin heartbeat handler (writer) and the webconsole
// .../agents/{id}/concurrency endpoint (reader).
LiveState concurrency.LiveStateStore
// AgentService is the v2.7 Agent BC AppService facade (C3).
AgentService *agentsvc.Service
// AgentRepo is the raw Agent repository (v2.7 D2-f s4). The worker boot-resume
// admin endpoint enumerates a worker's agents (ListByWorker) — a worker-level
// read with no fitting AppService method, so the repo is exposed directly.
AgentRepo agentpkg.Repository
// AgentActivityRepo is the append-only Agent activity-event repository (C2).
// The admin controller→center feedback surface (v2.7 D2-c-i activity sink)
// reads it back in tests; writes go through AgentService.AppendActivity.
AgentActivityRepo agentpkg.ActivityEventRepository
TeamRuleAuditRepo *ruleregistrysqlite.AuditRepo
// EnvControlSvc is the v2.7 Environment BC control-channel AppService
// (D1, ADR-0050, task #102) — backs the additive /admin/environment/...
// worker control endpoints.
EnvControlSvc *envservice.EnvControl
// ControlStreamBus is the v2.7 D5 slice-1 center-side SSE down-push bus. A
// single shared instance: the projector's ControlLog publishes appended
// commands here (after commit, best-effort), and the
// /admin/environment/worker/commands/stream endpoint subscribes workers to
// it. Same WorkerControlEvent log backs both push + poll.
ControlStreamBus *controlstream.Bus
// RuntimeFsDispatcher is the I5 (issue-921db054) agent-runtime-browser correlator
// — ONE shared instance: the webconsole runtime endpoints Register+await a req_id
// here, and the admin /admin/environment/agent/runtime-fs/response endpoint
// Resolves the worker's reply against it. Both servers must hold the SAME pointer.
RuntimeFsDispatcher *runtimefs.Dispatcher
MessageWriter *convservice.MessageWriter
ChannelMgmtSvc *convservice.ChannelManagementService
ParticipantMgmtSvc *convservice.ParticipantManagementService
CarryOverSvc *convservice.CarryOverService
ConvRefRepo conversation.ConversationMessageReferenceRepository
ReadStateRepo conversation.UserConversationReadStateRepository
ReadStateSvc *convservice.ReadStateService
InboxSvc *convservice.AgentInboxService
FollowStateRepo conversation.UserConversationFollowStateRepository
FollowStateSvc *convservice.FollowStateService
// WakeGuard is the ONE process-singleton wake-chain circuit breaker (I7-D1).
// It holds the rate/cycle/depth anti-storm runtime state shared across ALL
// agent→agent down-pushes. Hoisted onto App (formerly a webconsole-wiring
// local) so the reply-guardrail (T341) gates agent-authored reply nudges
// through the SAME instance as wake delivery — one shared budget, no
// ungoverned ping-pong. Config is resolved LIVE from center settings.
WakeGuard *wakeguard.Guard
// ReplyNudgeSvc is the server-side reply-guardrail (T341, 方案 A). At
// turn-end + TrueIdle the worker asks it which directed replies an idle agent
// still owes; it derives them from the message log + read-state, gates
// agent-authored ones through WakeGuard, and returns bounded re-inject prompts.
ReplyNudgeSvc *convservice.ReplyNudgeService
// OutboxRepo is the cross-BC outbox emitter (v2.7 D2-e-ii). The MessageWriter
// uses it to emit `conversation.message_added` in the same tx as the message
// append (the conversational-wake trigger). (The retired request_input →
// agent.awaiting_input emit no longer exists; AgentWorkItem was removed in F7.)
OutboxRepo outbox.Repository
// SecretManagement (P11 § 3.7b)
UserSecretRepo secretmgmt.UserSecretRepository
UserSecretSvc *secretservice.UserSecretService
// UserSecretResolveSvc gates plaintext via SecretResolutionService.
// v2.3-3b (task #29): wired alongside UserSecretSvc when master key is
// loaded, so the admin endpoint can serve secret:resolve to worker
// daemons that hold a `secret:resolve`-scoped admin token.
UserSecretResolveSvc *secretservice.SecretResolutionService
// AdminToken (v2.3-3a task #28) — bearer tokens that gate the admin
// endpoint. Server mode wires both fields; CLI mode (NewClientApp)
// leaves them nil — the CLI talks to a server that already has them.
AdminTokenRepo admintoken.Repository
AdminTokenSvc *admintokensvc.Service
// v2.6: Identity BC services.
IdentitySignupSvc *identity.SignupService
IdentitySigninSvc *identity.SigninService
IdentitySignoutSvc *identity.SignoutService
IdentityAuthSvc *identity.AuthService
IdentityPasscodeChangeSvc *identity.PasscodeChangeService
IdentityRepo identity.IdentityRepository
IdentityOrgRepo identity.OrganizationRepository
IdentityOrgCreateSvc *identity.OrganizationCreateService
IdentityOrgLifecycleSvc *identity.OrganizationLifecycleService
IdentityMemberRepo identity.MemberRepository
IdentityMemberAddSvc *identity.MemberAddService
IdentityMemberCreateUserSvc *identity.MemberCreateUserService
IdentityMemberRoleChangeSvc *identity.MemberRoleChangeService
IdentityMemberDisableSvc *identity.MemberDisableService
IdentityMemberRemoveSvc *identity.MemberRemoveService
IdentityAgentProvisionSvc *identity.AgentIdentityProvisionService
IdentityOrgUpdateSvc *identity.OrganizationUpdateService
IdentityInvitationRepo identity.InvitationRepository
// Observability Phase 4
QuerySvc *query.Service
FleetSvc *query.FleetSnapshotService
StatsSvc *query.StatsService
LogsSvc *query.LogsService
BlobStore blobstore.BlobStore
InsightSvc *insight.Service
InsightObservationRepo *insight.ObservationRepo
}
App carries everything CLI handlers need.
Two construction modes (v2.2 Phase B per conventions § 0.4):
- **Server mode**: NewApp opens the DB and wires every Service / Repo field. Used by `agent-center server` (handlers_system.go) which IS the process that owns the DB and serves the admin endpoint.
- **CLI mode**: NewClientApp builds a lightweight App with only Config + Clock + Client populated; every Service / Repo field is nil. CLI handlers go through Client to talk to a running server (the only legitimate AppService entry point per § 0.4).
Handlers that need to run in BOTH modes (rare; mostly only server boot + schema migrations) must consult whichever fields the active mode populates. The pattern across handlers_*.go (post-Phase B migration) is: prefer `a.Client.<Method>` over `a.<Svc>.<Method>`.
func NewApp ¶
NewApp wires the full dependency graph from a Config. The DB must already be open + migrated.
func NewClientApp ¶
NewClientApp constructs a lightweight CLI-mode App. The DB / Service / Repo fields are intentionally nil — handlers MUST go through Client (v2.2 Phase B; conventions § 0.4 "AppService is the only entry").
Use this for every CLI command except `agent-center server` (which IS the server and uses NewApp + an open DB).
func (*App) AdminCommands ¶
AdminCommands returns the admin command subtree per 03-cli-subcommands § 8.x. Phase 7 lands `backup`; v2.3-3a (task #28) adds the `token` group (create / list / revoke).
func (*App) WorkerCommands ¶
WorkerCommands returns the `worker` command tree (excluding the worker daemon `worker run` placeholder which lives in handlers_system.go).
v2.2 Phase B (per docs/plans/v2.2-audits/v22-B-cli-refactor-audit.md): every handler in this file now routes through a.Client (admin endpoint) when a Client is configured. A transitional fallback to direct Service / Repo access remains for the test path that constructs an App via newTestApp() without a Client; that fallback dies once the next phase of v2.2-B converts test scaffolding to use setupAdminServerForTests (see admin_client_testhelper.go).
type ChannelArchiveRequest ¶
type ChannelArchiveRequest struct {
Name string `json:"name"`
ArchivedBy string `json:"archived_by"`
}
ChannelArchiveRequest mirrors api archiveChannelReq.
type ChannelCreateRequest ¶
type ChannelCreateRequest struct {
Name string `json:"name"`
Description string `json:"description"`
CreatedBy string `json:"created_by"`
}
ChannelCreateRequest mirrors api createChannelReq.
type ChannelCreateResponse ¶
type ChannelCreateResponse struct {
ConversationID string `json:"conversation_id"`
EventID string `json:"event_id"`
}
ChannelCreateResponse mirrors the success projection.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the CLI-side admin transport. It dials either a unix-domain socket (default; cfg.Server.AdminSocketPath) or a TCP+TLS endpoint with SSH-style fingerprint pinning (v2.3-7b, task #27) — both go through the same code path; the kind is captured at construct-time.
Construct one per CLI invocation via NewClient (unix) or NewClientFromTarget (any). Zero value is invalid; methods that try to use it return ErrClientNotConfigured.
func NewClient ¶
NewClient returns a Client targeting the given unix socket path. timeout is applied per request; pass 0 for the default 30s.
Preserved unchanged for backward compat with v2.2 callers + tests. v2.3-7b callers wanting TCP+TLS should use NewClientFromTarget.
func NewClientFromTarget ¶
func NewClientFromTarget(target clienttransport.Target, fingerprint string, timeout time.Duration) (*Client, error)
NewClientFromTarget constructs a Client from a parsed transport target (unix or tcp) + optional fingerprint (mandatory for tcp). v2.3-7b (task #27). Returns an error rather than panicking when the fingerprint is missing/malformed for tcp — security-sensitive path.
func (*Client) AdminTokenCreate ¶
func (c *Client) AdminTokenCreate(ctx context.Context, req AdminTokenCreateRequest) (AdminTokenCreateResponse, error)
AdminTokenCreate POSTs /admin/admintoken/create. The caller must hold a bearer with `admin:token` scope.
func (*Client) AdminTokenList ¶
func (c *Client) AdminTokenList(ctx context.Context) ([]AdminTokenDTO, error)
AdminTokenList GETs /admin/admintoken/list.
func (*Client) AdminTokenRevoke ¶
func (c *Client) AdminTokenRevoke(ctx context.Context, req AdminTokenRevokeRequest) error
AdminTokenRevoke POSTs /admin/admintoken/revoke.
func (*Client) CarryOverFindByChildConv ¶
func (c *Client) CarryOverFindByChildConv(ctx context.Context, childConvID string) ([]ConversationMessageReferenceDTO, error)
CarryOverFindByChildConv GETs /admin/conversation/carry-over/find-by-child-conv?child_conversation_id=…
func (*Client) CarryOverFindBySourceMsg ¶
func (c *Client) CarryOverFindBySourceMsg(ctx context.Context, sourceMsgID string) ([]ConversationMessageReferenceDTO, error)
CarryOverFindBySourceMsg GETs /admin/conversation/carry-over/find-by-source-msg?source_message_id=…
func (*Client) ChannelArchive ¶
func (c *Client) ChannelArchive(ctx context.Context, req ChannelArchiveRequest) (EventIDResponse, error)
ChannelArchive POSTs /admin/conversation/channel/archive.
func (*Client) ChannelCreate ¶
func (c *Client) ChannelCreate(ctx context.Context, req ChannelCreateRequest) (ChannelCreateResponse, error)
ChannelCreate POSTs /admin/conversation/channel/create.
func (*Client) CollaborationEffectEvidence ¶
func (c *Client) CollaborationEffectEvidence(ctx context.Context, effectID, projectID string) (collaborationeffect.EvidenceResult, error)
func (*Client) CollaborationEffectsQuery ¶
func (c *Client) CollaborationEffectsQuery(ctx context.Context, filter collaborationeffect.Filter) (collaborationeffect.QueryResult, error)
func (*Client) ConvRefFindByChildConvID ¶
func (c *Client) ConvRefFindByChildConvID(ctx context.Context, childConvID string) ([]ConversationMessageReferenceDTO, error)
ConvRefFindByChildConvID GETs /admin/conversation/conv-ref/find-by-child-conv-id?child_conversation_id=…
func (*Client) ConvRefFindBySourceMsgID ¶
func (c *Client) ConvRefFindBySourceMsgID(ctx context.Context, sourceMsgID string) ([]ConversationMessageReferenceDTO, error)
ConvRefFindBySourceMsgID GETs /admin/conversation/conv-ref/find-by-source-msg-id?source_message_id=…
func (*Client) ConversationArchive ¶
func (c *Client) ConversationArchive(ctx context.Context, req ConversationArchiveRequest) (EventIDResponse, error)
ConversationArchive POSTs /admin/conversation/message-writer/archive.
func (*Client) ConversationClose ¶
func (c *Client) ConversationClose(ctx context.Context, req ConversationCloseRequest) (EventIDResponse, error)
ConversationClose POSTs /admin/conversation/message-writer/close.
func (*Client) ConversationFind ¶
func (c *Client) ConversationFind(ctx context.Context, kind, status string) ([]ConversationDTO, error)
ConversationFind GETs /admin/conversation/conv/find?kind=…&status=…
func (*Client) ConversationFindByID ¶
ConversationFindByID GETs /admin/conversation/conv/find-by-id?id=…
func (*Client) ConversationFindByName ¶
ConversationFindByName GETs /admin/conversation/conv/find-by-name?name=…
func (*Client) ConversationOpen ¶
func (c *Client) ConversationOpen(ctx context.Context, req ConversationOpenRequest) (ConversationOpenResponse, error)
ConversationOpen POSTs /admin/conversation/message-writer/open.
func (*Client) EventFind ¶
EventFind GETs /admin/observability/event/find with optional filters. Pass empty strings / 0 to omit a filter; the helper drops them.
func (*Client) EventFindByID ¶
EventFindByID GETs /admin/observability/event/find-by-id?id=…
func (*Client) FleetSnapshotRaw ¶
FleetSnapshotRaw GETs /admin/observability/fleet/snapshot?project_id=… and decodes into out (typically query.FleetSnapshot).
func (*Client) InspectRaw ¶
InspectRaw GETs /admin/observability/query/inspect?kind=…&id=… and decodes into out (typically query.InspectResult).
func (*Client) LogsOpen ¶
LogsOpen GETs /admin/observability/logs/open?kind=…&id=… and returns the gzipped body bytes plus the blob ref (from the X-Blob-Ref response header). Caller is responsible for decoding / streaming.
We deliberately return []byte rather than an io.ReadCloser because the underlying socket connection is closed when this method returns; streaming would require a different transport-level helper.
func (*Client) MessageAppend ¶
func (c *Client) MessageAppend(ctx context.Context, req MsgAppendRequest) (MsgAppendResponse, error)
MessageAppend POSTs /admin/conversation/msg/append.
func (*Client) MessageFindByConversationID ¶
func (c *Client) MessageFindByConversationID(ctx context.Context, convID string) ([]MessageDTO, error)
MessageFindByConversationID GETs /admin/conversation/msg/find-by-conversation-id?conversation_id=… Server hard-codes MessageFilter{Limit: 200}. For arbitrary-tail queries use MessageFindRecent below (v2.3-1).
func (*Client) MessageFindByID ¶
MessageFindByID GETs /admin/conversation/msg/find-by-id?id=…
func (*Client) MessageFindRecent ¶
MessageFindRecent GETs /admin/conversation/msg/find-recent?conversation_id=…&n=… (v2.3-1). n=0 lets the server pick the default (50). Returns messages oldest-first, mirroring MessageRepo.FindRecent's contract.
func (*Client) ParticipantInvite ¶
func (c *Client) ParticipantInvite(ctx context.Context, req ParticipantInviteRequest) (EventIDResponse, error)
ParticipantInvite POSTs /admin/conversation/participant/invite.
func (*Client) ParticipantKick ¶
func (c *Client) ParticipantKick(ctx context.Context, req ParticipantKickRequest) (EventIDResponse, error)
ParticipantKick POSTs /admin/conversation/participant/kick.
func (*Client) ParticipantLeave ¶
func (c *Client) ParticipantLeave(ctx context.Context, req ParticipantLeaveRequest) (EventIDResponse, error)
ParticipantLeave POSTs /admin/conversation/participant/leave (v2.3-1).
func (*Client) ProjectFindAll ¶
ProjectFindAll GETs /admin/workforce/project/find-all. v2.5.5 dropped the by-kind filter; the param is kept on the signature for callers that haven't been updated yet, but is no longer transmitted.
func (*Client) ProjectFindByID ¶
ProjectFindByID GETs /admin/workforce/project/find-by-id?id=…
func (*Client) QueryRaw ¶
QueryRaw POSTs /admin/observability/query/query and decodes the success body into `out` (any).
Handlers typically decode into a query.QueryResult; we don't take a compile dependency on the query package here so accept any.
func (*Client) SecretCreate ¶
func (c *Client) SecretCreate(ctx context.Context, req SecretCreateRequest) (SecretCreateResponse, error)
SecretCreate POSTs /admin/secret/user-secret/create.
func (*Client) SecretFindAll ¶
SecretFindAll GETs /admin/secret/user-secret/find-all?kind=…&state=…
func (*Client) SecretFindByID ¶
SecretFindByID GETs /admin/secret/user-secret/find-by-id?id=…
func (*Client) SecretFindByName ¶
SecretFindByName GETs /admin/secret/user-secret/find-by-name?name=…
func (*Client) SecretResolve ¶
SecretResolve POSTs /admin/secret/user-secret/resolve. Returns the decoded plaintext bytes; caller is responsible for wiping them after use (ADR-0026 § 5). Requires `secret:resolve` scope on the bearer.
func (*Client) SecretRevoke ¶
func (c *Client) SecretRevoke(ctx context.Context, req SecretRevokeRequest) (EventIDResponse, error)
SecretRevoke POSTs /admin/secret/user-secret/revoke.
func (*Client) SecretRotate ¶
func (c *Client) SecretRotate(ctx context.Context, req SecretRotateRequest) (EventIDResponse, error)
SecretRotate POSTs /admin/secret/user-secret/rotate.
func (*Client) SocketPath ¶
SocketPath returns the configured socket path (diagnostics). Empty when the Client was constructed from a TCP target.
func (*Client) StatsAggregateRaw ¶
StatsAggregateRaw GETs /admin/observability/stats/aggregate?scope=…&since=… and decodes into out (typically query.StatsResult). `since` is the raw query parameter value (handlers pre-format duration vs RFC3339).
func (*Client) WithToken ¶
WithToken sets the bearer token attached to every subsequent request. Returns the receiver to allow chaining at construction sites.
Empty strings clear the token (so tests can deliberately exercise the unauthenticated path).
func (*Client) WorkerEnroll ¶
func (c *Client) WorkerEnroll(ctx context.Context, req WorkerEnrollRequest) (WorkerEnrollResponse, error)
WorkerEnroll POSTs /admin/workforce/worker/enroll.
func (*Client) WorkerFindAll ¶
WorkerFindAll GETs /admin/workforce/worker/find-all.
func (*Client) WorkerFindByID ¶
WorkerFindByID GETs /admin/workforce/worker/find-by-id?id=…
type ClientError ¶
type ClientError struct {
Method string
Path string
Status int
Code string // server-side error code (from the JSON envelope)
Message string // server-side message
Body string // raw body for unrecognised shapes
}
ClientError carries non-2xx admin endpoint responses.
func (*ClientError) IsConflict ¶
func (e *ClientError) IsConflict() bool
IsConflict reports whether the error is a 409 response.
func (*ClientError) IsNotFound ¶
func (e *ClientError) IsNotFound() bool
IsNotFound reports whether the error is a 404 response.
type Command ¶
type Command struct {
Name string
Summary string
LongHelp string
Subcommands []*Command
Run Handler
// Flags can be registered up-front via this hook. The hook gets a
// fresh *flag.FlagSet to register on; the returned Handler receives
// the parsed-arg slice.
Flags func(fs *flag.FlagSet) Handler
// Group is the root-level grouping label used by `agent-center help`
// to keep ~30 top-level commands legible. Empty defaults to "Other".
// Only top-level commands are grouped — nested subcommands inherit
// implicitly.
Group string
// Examples are concrete, runnable invocations rendered under
// `Examples:` in `--help` output. Per P11 § 3.9: each leaf command
// should ship at least the happy path + one `--format=json` variant
// so users discover scripting paths without reading docs.
Examples []string
// HelpFlags is an optional display-only flag registrar. Used by
// `lazyApp` wrappers where `Run` is set (real handler) but flag
// metadata still needs to render in `--help`. printNodeHelp falls
// back to HelpFlags when Flags is nil. If both are nil, no Flags:
// section renders.
HelpFlags func(fs *flag.FlagSet)
}
Command is a node in the command tree. A node is either a group (has Subcommands) or a leaf (has Run). It cannot be both.
func AdminBlobMigratePlaceholder ¶
func AdminBlobMigratePlaceholder() *Command
AdminBlobMigratePlaceholder returns the `admin blob-migrate` stub.
func AgentRuntimeCommand ¶
func AgentRuntimeCommand() *Command
AgentRuntimeCommand is the `worker agent-runtime` entry (T854 D6, design §4.5/§5): ONE agent's self-contained runtime, run as its own OS process. The worker's launcher fork/execs this subcommand (os.Executable() worker agent-runtime --agent-id X --sock-dir D) per agent and rebuilds it on exit.
It shares the worker's config/token bootstrap (it does NOT re-enroll — it loads the token the worker persisted), self-builds its center client, runs Boot self-recovery, then serves control commands the worker proxies over the unix socket in --sock-dir. The flag surface mirrors `worker run` so an operator/launcher can pass the same admin-target/token/fingerprint, plus --agent-id and --sock-dir.
func AgentSupervisorCommand ¶
func AgentSupervisorCommand() *Command
AgentSupervisorCommand is the v2.7 (D2-f s1) persistent per-agent SUPERVISOR entry. It is a thin, long-lived process that OWNS the agent's claude (claude == its child) so a worker-daemon crash/restart does NOT kill claude: the supervisor setsids into its own session/group to ESCAPE a killpg of the daemon's group, holds claude's stdin open, and continuously drains claude's stdout to a persistent offset cursor (events.jsonl).
SCOPE: additive + NOT wired into the daemon (no socket, no attach/reattach — those are s2/s3). System-audience (operators do not invoke it directly), so it lives under the `worker` group alongside mcp-host / run / shim.
MINIMAL KEY SURFACE: the supervisor receives only the daemon-generated mcp-config FILE PATH via --mcp-config-path. It NEVER takes or holds the worker token; the daemon generates the mcp-config (which carries the token) and the supervisor just points claude at the file.
func BootstrapCommand ¶
func BootstrapCommand() *Command
BootstrapCommand returns the `bootstrap` admin command tree. v1 surface:
- bootstrap check-systemd → validate the worker user-systemd unit contains KillMode=process (ADR-0018 hard requirement). Designed to be invoked by install-worker.sh AND from the worker daemon at startup so manual tampering is caught.
func ExecutorCommand ¶
func ExecutorCommand() *Command
ExecutorCommand is the F1 (agent-concurrent-execution §4/§11.2) per-task EXECUTOR entry. It is the forked, pure-compute worker the orchestrator (监工) spawns for ONE task: it reads its goal from <agent-root>/executors/<id>/input.json, runs the model-routed agent CLI inside its own isolated git worktree, streams progress, and writes output.json + status — all over the F2 file protocol.
CRITICAL (the executor's defining property): it NEVER connects to the center or mcp and holds NO credentials. Unlike mcp-host / agent-supervisor it takes no admin URL, no worker token, and is launched (by executor.Spawner) with a sanitized, mcp-free environment. Binding is purely its --agent-root + --executor-id. System-audience (the orchestrator spawns it, operators do not), so it lives under the `worker` group alongside mcp-host / agent-supervisor.
func InstallCenterCommand ¶
func InstallCenterCommand() *Command
InstallCenterCommand is the `install center` leaf — the operator's one command for "spin up an agent-center server on this machine".
func InstallCommand ¶
func InstallCommand() *Command
InstallCommand is the parent group; printing help when invoked without a subcommand. Per the v2.4 first-mile spec, the operator types `agent-center install center` or `... install worker`.
func InstallTestInstanceCommand ¶
func InstallTestInstanceCommand() *Command
InstallTestInstanceCommand spins up an isolated 1-center + N-worker sandbox.
func InstallWorkerCommand ¶
func InstallWorkerCommand() *Command
InstallWorkerCommand is the `install worker` leaf — the operator's one command for "join this machine to the cluster as a worker".
func ListLocalCentersCommand ¶
func ListLocalCentersCommand() *Command
ListLocalCentersCommand surfaces all local center deployments (v2.7.1 #211).
func ListLocalWorkersCommand ¶
func ListLocalWorkersCommand() *Command
ListLocalWorkersCommand surfaces all local worker deployments (v2.8 #170).
func ListTestInstancesCommand ¶
func ListTestInstancesCommand() *Command
ListTestInstancesCommand lists the sandboxes under ~/.agent-center-test. Named with the `list-` prefix for symmetry with list-local-centers (#211) / list-local-workers (#170).
func MCPHostCommand ¶
func MCPHostCommand() *Command
MCPHostCommand is the per-agent stdio MCP server entry (v2.7 b3-i, ADR-0049). One process == one agent: it bridges MCP tool calls from a claude process to the center's admin agent-tool endpoints. The daemon spawns it via --mcp-config with per-server env; it is system-audience (operators do not invoke it directly), so it lives under the `worker` group alongside the other daemon-internal entries (run / shim).
Binding comes ENTIRELY from env (process-fixed):
- AC_MCP_AGENT_ID operating agent id, injected into every admin call body; NEVER taken from tool args (required).
- AC_MCP_ADMIN_URL admin endpoint: unix:/path or tcp://host:port (required).
- AC_MCP_WORKER_TOKEN worker bearer token (owner worker:<id>).
- AC_MCP_SERVER_FINGERPRINT pinned cert fingerprint, required when AC_MCP_ADMIN_URL is tcp://...
- AC_MCP_RUNTIME_SOCKET optional local runtime control socket for runtime-authoritative supervisor execution state.
- AC_MCP_TIER_TOOLS optional bool, default true. Set false only for clients that already own deferred MCP discovery.
- AC_MCP_GENERATION optional non-negative int identifying the launching supervisor generation for plan-rule snapshot audits.
func MigrateGroupCommand ¶
func MigrateGroupCommand() *Command
MigrateGroupCommand is the parent of `migrate up` + `migrate v1-to-v2`. It carries no Run handler — invoking `migrate` alone prints help.
func MigrateOrphanConditionsCommand ¶
func MigrateOrphanConditionsCommand() *Command
MigrateOrphanConditionsCommand implements `agent-center migrate orphan-conditions`.
func MigrateUpCommand ¶
func MigrateUpCommand() *Command
MigrateUpCommand replaces the v1-era top-level `migrate` leaf. It runs pending migrations against the configured SQLite file. Behavior is preserved verbatim from the v1 form (target=N supported).
func MigrateV1ToV2Command ¶
func MigrateV1ToV2Command() *Command
MigrateV1ToV2Command implements `agent-center migrate v1-to-v2`.
Per P12 S12 audit (docs/plans/phase-12-audits/s12-migration-tool-audit.md):
- --dry-run reports planned ops (bridge row counts; current vs target version)
- --apply runs them: bridge tables → JSON archive → drop via 0025 → Up to targetSchemaVersion (currently 28 — v2.0 GA was 25, v2.1-C added 0026, v2.1-E added 0027, v2.3-3a added 0028 admin_tokens)
- Idempotent: if already at v2 (currentVer >= targetSchemaVersion), exits 0 with "already at v2"
- Refuses to run silently — neither flag → usage error
func ServerCommand ¶
func ServerCommand() *Command
ServerCommand returns the `server` mode command. It needs to construct its own deps (open DB, run migrations) because it's the entry point before any other command runs.
func SystemCommands ¶
SystemCommands returns top-level mode + admin commands.
`server` / `migrate` actually run; `supervisor` / `worker` / `admin blob-migrate` are placeholder stubs per plan-1 § 3.1.4 — they exist so the CLI surface is stable and exit cleanly with reason `not_implemented_in_phase_1`.
func UninstallCenterCommand ¶
func UninstallCenterCommand() *Command
UninstallCenterCommand removes a center install. Mirrors the install center flag surface so operators don't have to think about where things landed.
func UninstallCommand ¶
func UninstallCommand() *Command
UninstallCommand is the parent group for `uninstall center|worker`.
func UninstallTestInstanceCommand ¶
func UninstallTestInstanceCommand() *Command
UninstallTestInstanceCommand tears down a sandbox: bootout the launchd labels + remove the namespace subtree. Confined to ~/.agent-center-test/<id>/.
func UninstallWorkerCommand ¶
func UninstallWorkerCommand() *Command
UninstallWorkerCommand removes a worker install. --worker-id is required since multi-worker installs share a parent prefix.
func UpgradeCenterCommand ¶
func UpgradeCenterCommand() *Command
UpgradeCenterCommand is the explicit upgrade-only entry point for the center. Shares the install-center flag surface to keep muscle memory + the existing flag docs unchanged.
func UpgradeCommand ¶
func UpgradeCommand() *Command
UpgradeCommand is the parent group for `upgrade center|worker`.
func UpgradeWorkerCommand ¶
func UpgradeWorkerCommand() *Command
UpgradeWorkerCommand mirrors UpgradeCenterCommand for the worker install. Requires --worker-id so the right worker subtree is targeted on multi-worker hosts.
func WorkerRecoverDeliveryCommand ¶
func WorkerRecoverDeliveryCommand() *Command
WorkerRecoverDeliveryCommand is the operator-facing manual recovery delivery path. It runs on the worker/operator machine, optionally commits/pushes a retained worktree, then reports a manual_recovery delivery through the same report_delivery agent-tool the runtime uses. The center persists/audits the result; it never performs git operations.
func WorkerRunCommand ¶
func WorkerRunCommand() *Command
WorkerRunCommand is the `worker run` daemon entry (v2.7 (b) cutover). The worker daemon now ships INSIDE the unified `agent-center` binary so its os.Executable() can route the `worker agent-supervisor` and `worker mcp-host` subcommands the daemon spawns (the spawn-bug fix; the retired standalone `agent-center-worker- daemon` was flag-only and could not route them).
§ 0.4 is honored by construction: the daemon talks to the center ONLY via the admin endpoint (AdminClient) and never opens the SQLite file — so this CLI subcommand holds no DB handle. The flag set is kept STRICTLY in parity with the (retiring) standalone binary so operator behavior and Tester runbooks are unchanged; the real bootstrap lives in workerdaemon.RunDaemon (single source, shared with the thin standalone wrapper).
func WorkerShimPlaceholder ¶
func WorkerShimPlaceholder() *Command
WorkerShimPlaceholder is the `worker shim` entry point. The shim runtime is daemon-internal; this is a thin CLI hook. Daemon spawns shim via this entry; users do not directly invoke it (audience=Sys per 03-cli § 8.3).
type ConversationArchiveRequest ¶
type ConversationArchiveRequest struct {
ConversationID string `json:"conversation_id"`
Version int `json:"version"`
ArchivedBy string `json:"archived_by"`
}
ConversationArchiveRequest is the POST body for message-writer/archive.
type ConversationCloseRequest ¶
type ConversationCloseRequest struct {
ConversationID string `json:"conversation_id"`
Version int `json:"version"`
Reason string `json:"reason"`
Message string `json:"message"`
}
ConversationCloseRequest is the POST body for message-writer/close.
type ConversationDTO ¶
type ConversationDTO struct {
ID string `json:"id"`
Kind string `json:"kind"`
Name string `json:"name"`
Description string `json:"description"`
Status string `json:"status"`
ParentConversationID string `json:"parent_conversation_id"`
CreatedBy string `json:"created_by"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
Version int `json:"version"`
ArchivedAt string `json:"archived_at,omitempty"`
ArchivedBy string `json:"archived_by,omitempty"`
Participants []ParticipantDTO `json:"participants"`
}
ConversationDTO mirrors admin api convMap.
type ConversationMessageReferenceDTO ¶
type ConversationMessageReferenceDTO struct {
ID string `json:"id"`
ChildConversationID string `json:"child_conversation_id"`
SourceConversationID string `json:"source_conversation_id"`
SourceMessageID string `json:"source_message_id"`
CreatedBy string `json:"created_by"`
CreatedAt string `json:"created_at"`
}
ConversationMessageReferenceDTO mirrors admin api refsToMap entries.
type ConversationOpenRequest ¶
type ConversationOpenRequest struct {
Kind string `json:"kind"`
Name string `json:"name"`
Description string `json:"description"`
ParentConversationID string `json:"parent_conversation_id"`
Participants []conversation.ParticipantElement `json:"participants"`
CreatedBy string `json:"created_by"`
}
ConversationOpenRequest is the POST body for message-writer/open.
type ConversationOpenResponse ¶
type ConversationOpenResponse struct {
ConversationID string `json:"conversation_id"`
EventID string `json:"event_id"`
}
ConversationOpenResponse mirrors the success projection.
type ErrorReason ¶
ErrorReason captures the structured error returned to the user via JSON. Aligns with 03-cli § 6.
type EventDTO ¶
type EventDTO struct {
ID string `json:"id"`
EventType string `json:"event_type"`
Actor string `json:"actor"`
Refs map[string]any `json:"refs"`
Payload map[string]any `json:"payload"`
CorrelationID string `json:"correlation_id"`
DecisionID string `json:"decision_id"`
OccurredAt string `json:"occurred_at"`
}
EventDTO mirrors admin api eventMap.
type EventFindFilter ¶
type EventFindFilter struct {
EventType string
TaskID string
ExecutionID string
IssueID string
ConversationID string
WorkerID string
Limit int
}
EventFindFilter is the wire-side filter for EventFind.
type EventIDResponse ¶
type EventIDResponse struct {
EventID string `json:"event_id"`
}
EventIDResponse is the generic single-event-id success shape used by many admin write endpoints (`{"event_id": "..."}`).
type ExitCode ¶
type ExitCode int
ExitCode pairs a numeric exit value with optional structured info that the router can post-process (e.g. JSON-format mode).
func HandleClientError ¶
HandleClientError translates an admin Client error to the same (reason, exit-code) shape as HandleDomainError. This is the post-v2.2-B handler error path: domain errors come back over the wire wrapped in *ClientError, with the server-side code in ClientError.Code mapping to the same reason strings handlers used pre-migration.
Mapping rules:
- server-side codes (not_found, version_conflict, already_exists, terminal, invalid_transition, invalid_input) map to exit-code equivalents from the legacy domain table.
- ErrServerUnreachable / ErrClientNotConfigured surface a friendly "is the server running?" hint with ExitBusinessError.
- everything else falls through to ExitBusinessError with the raw error message preserved in the message field.
func HandleDomainError ¶
HandleDomainError formats and prints err using format ("human" or "json") and returns the matching exit code. Falls back to internal_error / ExitBusinessError for unknown error types.
func MapDomainError ¶
MapDomainError translates a workforce/conversation domain error to a (reason, exit-code) pair suitable for PrintError. Returns (false, …) if the error is not a known sentinel — caller emits a generic `internal_error` line and exits ExitBusinessError.
type Handler ¶
Handler is the signature of a leaf command implementation.
The framework parses positional + flag arguments before calling the handler. Handler implementations write business output to `out` (stdout) and diagnostics to `err` (stderr) — they MUST NOT call os.Exit; return an Exit struct instead.
type InstallState ¶
type InstallState int
InstallState reflects the outcome of detectExistingInstall.
const ( InstallStateUnknown InstallState = iota // InstallStateFresh = no prior install at prefix; A2 will write // everything fresh. InstallStateFresh // InstallStateSameVersion = `<prefix>/current` already points at // this binary's version; the install is idempotent. InstallStateSameVersion // InstallStateUpgrade = `<prefix>/current` exists but points at a // different version; A5 will perform symlink swap. InstallStateUpgrade )
type MessageDTO ¶
type MessageDTO struct {
ID string `json:"id"`
ConversationID string `json:"conversation_id"`
SenderIdentityID string `json:"sender_identity_id"`
ContentKind string `json:"content_kind"`
Content string `json:"content"`
Direction string `json:"direction"`
InputRequestRef string `json:"input_request_ref"`
PostedAt string `json:"posted_at"`
}
MessageDTO mirrors admin api messageMap.
type MsgAppendRequest ¶
type MsgAppendRequest struct {
ConversationID string `json:"conversation_id"`
SenderIdentityID string `json:"sender_identity_id"`
ContentKind string `json:"content_kind"`
Content string `json:"content"`
Direction string `json:"direction"`
InputRequestRef string `json:"input_request_ref"`
}
MsgAppendRequest is the POST body for /admin/conversation/msg/append.
type MsgAppendResponse ¶
type MsgAppendResponse struct {
MessageID string `json:"message_id"`
EventID string `json:"event_id"`
}
MsgAppendResponse mirrors the success projection.
type ParticipantDTO ¶
type ParticipantDTO struct {
IdentityID string `json:"identity_id"`
Role string `json:"role"`
JoinedAt any `json:"joined_at"`
JoinedBy string `json:"joined_by"`
LeftAt any `json:"left_at,omitempty"`
LeftReason string `json:"left_reason,omitempty"`
}
ParticipantDTO mirrors one entry of the admin api convMap "participants".
type ParticipantInviteRequest ¶
type ParticipantInviteRequest struct {
ConversationName string `json:"conversation_name"`
IdentityID string `json:"identity_id"`
Role string `json:"role"`
InvitedBy string `json:"invited_by"`
}
ParticipantInviteRequest mirrors api inviteParticipantReq.
type ParticipantKickRequest ¶
type ParticipantKickRequest struct {
ConversationName string `json:"conversation_name"`
IdentityID string `json:"identity_id"`
KickedBy string `json:"kicked_by"`
Reason string `json:"reason"`
}
ParticipantKickRequest mirrors api kickParticipantReq.
type ParticipantLeaveRequest ¶
type ParticipantLeaveRequest struct {
ConversationName string `json:"conversation_name"`
IdentityID string `json:"identity_id"`
Reason string `json:"reason"`
}
ParticipantLeaveRequest mirrors api leaveParticipantReq (v2.3-1). IdentityID may be empty — server defaults to the actor.
type ProjectDTO ¶
type ProjectDTO struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
OrganizationID string `json:"organization_id"`
Version int `json:"version"`
CreatedAt string `json:"created_at"`
}
ProjectDTO mirrors admin api projectMap. v2.7 #131 PR-3: repointed to the pm.Project model — tags dropped (pm.Project has none), organization_id surfaced.
type QueryRequest ¶
type QueryRequest struct {
Resource string `json:"resource"`
Status string `json:"status"`
ProjectID string `json:"project_id"`
WorkerID string `json:"worker_id"`
TaskID string `json:"task_id"`
ExecutionID string `json:"execution_id"`
IssueID string `json:"issue_id"`
Opener string `json:"opener"`
EventType string `json:"event_type"`
Limit int `json:"limit"`
Cursor string `json:"cursor"`
}
QueryRequest mirrors api queryReq (POST body for /observability/query/query).
type Router ¶
Router carries shared application state (DB, services, etc.) and the root command tree. Construct via NewRouter then add commands via Add.
func BuildRouter ¶
BuildRouter constructs the full command tree.
The router opens the DB lazily — only when a resource command is run (i.e. workforce / conversation handlers). `version` / `--help` / `supervisor` / `worker run` / `admin blob-migrate` placeholders all skip DB construction.
Returns the router + the resolved config path so main.go can strip the --config flag from args before dispatching.
func (*Router) Add ¶
Add inserts a sub-command tree at the given path (e.g. ["worker", "proposal"]). The leaf Command is appended as the last element's Subcommands.
func (*Router) HelpCommand ¶
HelpCommand is the `agent-center help [topic]` synthetic command. It is registered by BuildRouter so users can discover the rest of the tree without remembering exact subcommand names.
type SecretCreateRequest ¶
type SecretCreateRequest struct {
Name string `json:"name"`
Kind string `json:"kind"`
Plaintext string `json:"plaintext"`
}
SecretCreateRequest mirrors api secretCreateReq.
type SecretCreateResponse ¶
type SecretCreateResponse struct {
ID string `json:"id"`
Name string `json:"name"`
EventID string `json:"event_id"`
}
SecretCreateResponse mirrors api success body (id + name + event_id).
type SecretResolveResponse ¶
type SecretResolveResponse struct {
ID string `json:"id"`
Name string `json:"name"`
PlaintextBase64 string `json:"plaintext_base64"`
}
SecretResolveResponse mirrors the server's secret resolve envelope. PlaintextBase64 is std base64 of the raw bytes (NOT URL-safe).
type SecretRevokeRequest ¶
type SecretRevokeRequest struct {
ID string `json:"id"`
Reason string `json:"reason"`
Message string `json:"message"`
Version int `json:"version"`
}
SecretRevokeRequest mirrors api secretRevokeReq.
type SecretRotateRequest ¶
type SecretRotateRequest struct {
ID string `json:"id"`
NewPlaintext string `json:"new_plaintext"`
Version int `json:"version"`
}
SecretRotateRequest mirrors api secretRotateReq.
type UserSecretDTO ¶
type UserSecretDTO struct {
ID string `json:"id"`
Name string `json:"name"`
Kind string `json:"kind"`
State string `json:"state"`
CreatedAt string `json:"created_at"`
CreatedBy string `json:"created_by"`
Version int `json:"version"`
RevokedAt string `json:"revoked_at,omitempty"`
RevokedBy string `json:"revoked_by,omitempty"`
RevokedReason string `json:"revoked_reason,omitempty"`
RevokedMessage string `json:"revoked_message,omitempty"`
RotatedAt string `json:"rotated_at,omitempty"`
LastUsedAt string `json:"last_used_at,omitempty"`
}
UserSecretDTO mirrors admin api secretMap.
type WebConsoleEnrollWiring ¶
type WebConsoleEnrollWiring struct {
BootstrapHost string // e.g. "192.168.1.10:7300" or "127.0.0.1:7300"
Fingerprint string // SSH-style sha256:HH:HH:...
}
WebConsoleEnrollWiring carries the values the AddWorkerModal needs to render a working install command for the worker box. Both are known by ServerCommand after the admin TCP listener boots: the fingerprint comes from AdminTransportInfo, the bootstrap host is derived from the admin_tcp_listen config + the operator-facing hostname (or 127.0.0.1 when the listener is loopback-only).
type WorkerDTO ¶
type WorkerDTO struct {
WorkerID string `json:"worker_id"`
Status string `json:"status"`
Capabilities []string `json:"capabilities"`
Version int `json:"version"`
EnrolledAt string `json:"enrolled_at"`
LastHeartbeatAt string `json:"last_heartbeat_at,omitempty"`
SystemInfo workforce.SystemInfo `json:"system_info,omitempty"`
}
WorkerDTO mirrors admin api workerMap.
type WorkerEnrollRequest ¶
type WorkerEnrollRequest struct {
WorkerID string `json:"worker_id"`
Capabilities []string `json:"capabilities"`
}
WorkerEnrollRequest is the POST body for /admin/workforce/worker/enroll.
type WorkerEnrollResponse ¶
type WorkerEnrollResponse struct {
WorkerID string `json:"worker_id"`
EventID string `json:"event_id"`
Version int `json:"version"`
}
WorkerEnrollResponse is the success body.
type WriterAlias ¶
WriterAlias is io.Writer; aliased so cmd/agent-center can refer to it without re-importing io.
Source Files
¶
- admin_bootstrap.go
- admin_client.go
- admin_client_admintoken.go
- admin_client_conversation.go
- admin_client_observability.go
- admin_client_secret.go
- admin_client_testhelper.go
- admin_client_workforce.go
- admin_wiring.go
- app.go
- build.go
- build_version.go
- decision_timeout_wiring.go
- dispatch_wake_targets.go
- errors.go
- format.go
- handlers_admin.go
- handlers_agent_runtime.go
- handlers_agentsupervisor.go
- handlers_bootstrap.go
- handlers_executor.go
- handlers_install.go
- handlers_list_centers.go
- handlers_list_workers.go
- handlers_mcphost.go
- handlers_migrate_orphan_conditions.go
- handlers_migrate_v1_to_v2.go
- handlers_system.go
- handlers_test_instance.go
- handlers_uninstall.go
- handlers_upgrade.go
- handlers_worker.go
- handlers_worker_recover_delivery.go
- handlers_worker_run.go
- help_topics.go
- install_errors.go
- install_fs.go
- install_platform.go
- install_upgrade.go
- reminder_wiring.go
- router.go
- sweep_candidates.go
- team_member_resolver.go
- test_instance_agent.go
- test_instance_seed.go
- webconsole_wiring.go