agent/.core/reference/docs/primitives.md

170 lines
3.6 KiB
Markdown
Raw Permalink Normal View History

---
title: Core Primitives
description: The repeated shapes that make CoreGO easy to navigate.
---
# Core Primitives
CoreGO is easiest to use when you read it as a small vocabulary repeated everywhere. Most of the framework is built from the same handful of types.
## Primitive Map
| Type | Used For |
|------|----------|
| `Options` | Input values and lightweight metadata |
| `Result` | Output values and success state |
| `Service` | Lifecycle-managed components |
| `Message` | Broadcast events |
| `Query` | Request-response lookups |
| `Task` | Side-effecting work items |
## `Option` and `Options`
`Option` is one key-value pair. `Options` is an ordered slice of them.
```go
opts := core.Options{
{Key: "name", Value: "brain"},
{Key: "path", Value: "prompts"},
{Key: "debug", Value: true},
}
```
Use the helpers to read values:
```go
name := opts.String("name")
path := opts.String("path")
debug := opts.Bool("debug")
hasPath := opts.Has("path")
raw := opts.Get("name")
```
### Important Details
- `Get` returns the first matching key.
- `String`, `Int`, and `Bool` do not convert between types.
- Missing keys return zero values.
- CLI flags with values are stored as strings, so `--port=8080` should be read with `opts.String("port")`, not `opts.Int("port")`.
## `Result`
`Result` is the universal return shape.
```go
r := core.Result{Value: "ready", OK: true}
if r.OK {
fmt.Println(r.Value)
}
```
It has two jobs:
- carry a value when work succeeds
- carry either an error or an empty state when work does not succeed
### `Result.Result(...)`
The `Result()` method adapts plain Go values and `(value, error)` pairs into a `core.Result`.
```go
r1 := core.Result{}.Result("hello")
r2 := core.Result{}.Result(file, err)
```
This is how several built-in helpers bridge standard-library calls.
## `Service`
`Service` is the managed lifecycle DTO stored in the registry.
```go
svc := core.Service{
Name: "cache",
Options: core.Options{
{Key: "backend", Value: "memory"},
},
OnStart: func() core.Result {
return core.Result{OK: true}
},
OnStop: func() core.Result {
return core.Result{OK: true}
},
OnReload: func() core.Result {
return core.Result{OK: true}
},
}
```
### Important Details
- `OnStart` and `OnStop` are used by the framework lifecycle.
- `OnReload` is stored on the service DTO, but CoreGO does not currently call it automatically.
- The registry stores `*core.Service`, not arbitrary typed service instances.
## `Message`, `Query`, and `Task`
These are simple aliases to `any`.
```go
type Message any
type Query any
type Task any
```
That means your own structs become the protocol:
```go
type deployStarted struct {
Environment string
}
type workspaceCountQuery struct{}
type syncRepositoryTask struct {
Name string
}
```
## `TaskWithIdentifier`
Long-running tasks can opt into task identifiers.
```go
type indexedTask struct {
ID string
}
func (t *indexedTask) SetTaskIdentifier(id string) { t.ID = id }
func (t *indexedTask) GetTaskIdentifier() string { return t.ID }
```
If a task implements `TaskWithIdentifier`, `PerformAsync` injects the generated `task-N` identifier before dispatch.
## `ServiceRuntime[T]`
`ServiceRuntime[T]` is the small helper for packages that want to keep a Core reference and a typed options struct together.
```go
type agentServiceOptions struct {
WorkspacePath string
}
type agentService struct {
*core.ServiceRuntime[agentServiceOptions]
}
runtime := core.NewServiceRuntime(c, agentServiceOptions{
WorkspacePath: "/srv/agent-workspaces",
})
```
It exposes:
- `Core()`
- `Options()`
- `Config()`
This helper does not register anything by itself. It is a composition aid for package authors.