project

package
v0.8.66 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 19, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package project manages per-project configuration and lifecycle state.

Each island is represented by a project: (name, repo, agent, resources, desired state). Config persists to ~/.dejima/projects/<name>/config.toml.

Index

Constants

View Source
const (
	PortModeRO = "ro"
	PortModeRW = "rw"
)

Port access modes. V1 grants are read-only; "rw" is reserved for the read-write milestone (docs/port-island-spec.md §6) and rejected at grant time until then.

View Source
const (
	RoleProject = ""
	RoleHome    = "home"
)

Island roles. Empty (RoleProject) is the default work/coding island. RoleHome marks a persistent "Home Island" that hosts an always-on assistant orchestrator (the brain), which reaches host content only through the Port and spawns work islands via the API. See docs/port-island-spec.md §3.2.

Variables

View Source
var (
	// ErrNoSuchAgent: the ref matched neither an id nor any label.
	ErrNoSuchAgent = errors.New("no such agent")
	// ErrAmbiguousAgent: the ref matched more than one agent's label.
	ErrAmbiguousAgent = errors.New("ambiguous agent")
)

Sentinel error kinds for agent-ref resolution, so callers can branch on the failure mode (e.g. the mailbox treats "no match" as a permissive pass-through but rejects "ambiguous"). Wrapped errors carry the human-readable detail.

Functions

func Delete

func Delete(name string) error

Delete removes the project's on-host config directory.

func DeriveNameFromRepo

func DeriveNameFromRepo(repo string) string

DeriveNameFromRepo extracts a reasonable default name from a repo URL or path.

func EnsureProjectSubdirs

func EnsureProjectSubdirs(name string) error

EnsureProjectSubdirs creates intake/, exports/, logs/ for a project.

func Exists

func Exists(name string) bool

Exists reports whether a project with this name has a config on disk.

func HostOwner added in v0.8.3

func HostOwner() string

HostOwner is the tenant id attributed to the host operator: the owner of islands created via the trusted local socket or a RoleOwner token, and the backfill value for islands that predate ownership. Configurable via DEJIMA_HOST_OWNER; defaults to "aoos".

func PrimaryAgentID

func PrimaryAgentID(name string) string

PrimaryAgentID is the id a brand-new island's primary agent gets: the island's mnemonic letter + "1" (e.g. "Port" → "p1"), matching the scheme NextAgentID uses for added agents. Legacy islands migrated by EnsureAgents keep "a1" so a live attached session isn't renamed out from under the user.

func ResolveAgentRef added in v0.6.9

func ResolveAgentRef[T AgentRef](agents []T, ref string) (string, error)

ResolveAgentRef maps a user-supplied agent reference to a concrete agent id, over an arbitrary set of agents. Resolution order (id always wins, for back-compat — every place that took an id keeps working):

  1. exact id match → that id.
  2. else case-insensitive label match → the matched agent's id.
  3. multiple label matches → an "ambiguous" error listing each id(label), directing the user to the id.
  4. no match → a "no such agent" error.

ref is trimmed of surrounding whitespace first. An empty ref returns an error (callers that mean "the primary" should not route through here).

func ValidateCapabilityTarget

func ValidateCapabilityTarget(target string) error

ValidateCapabilityTarget checks a capability target name — a macOS Shortcut name or a ~/.dejima/capabilities/ script basename. It is intentionally more permissive than ValidateName (real Shortcut names carry spaces and mixed case) but stays safe as a single filename component: no path separators or traversal, no control characters, bounded length. The strict mode/ownership checks for the Linux script adapter happen at execution time, not here.

func ValidateName

func ValidateName(name string) error

ValidateName ensures a name is safe to use in container/volume names.

Types

type AgentRef added in v0.6.9

type AgentRef interface {
	RefID() string
	RefLabel() string
}

AgentRef is the minimal (id, label) view the agent-ref resolver needs. Both an AgentSpec (daemon-side) and the CLI's api.AgentInfo satisfy it, so ONE resolver backs every "address an agent by name" path. The resolver never reads anything else off an agent, keeping it usable from either trust domain.

type AgentSpec

type AgentSpec struct {
	ID   string `toml:"id"`   // stable per-island handle: "a1", "a2", …
	Type string `toml:"type"` // handler id: "claude-code", "codex", "headless"
	// Label is a user-facing, renamable name (e.g. "frontend"). Cosmetic.
	Label string `toml:"label,omitempty"`
	// Cmd is the entrypoint for headless agents; empty for the CLI agents.
	Cmd string `toml:"cmd,omitempty"`
	// Tmux is the in-container tmux session name for interactive agents. Empty
	// for headless. The migrated primary keeps "dejima" so a live attached
	// session survives a daemon upgrade; new agents use "agent-<id>".
	Tmux string `toml:"tmux,omitempty"`
	// Branch is the git branch backing this agent's worktree.
	Branch string `toml:"branch,omitempty"`
	// Worktree is the container path the agent works in: "/workspace" for the
	// primary, "/workspace/.agents/<id>" for the rest.
	Worktree string `toml:"worktree,omitempty"`
	// Restart enables supervise-and-restart-on-crash for co-located headless agents.
	Restart bool `toml:"restart,omitempty"`
	// Provider names which daemon LLM-provider credential this agent uses (see
	// internal/providercreds), e.g. "anthropic". Empty → the store default. Only
	// meaningful when the handler RequiresProviderKey.
	Provider string `toml:"provider,omitempty"`
	// Model is the "provider/model" string handed to the framework (via the
	// DEJIMA_MODEL env the per-agent shim translates). Empty → unset (the user
	// picks explicitly; there is no baked-in default).
	Model string `toml:"model,omitempty"`
	// Ephemeral marks an agent-spawned sub-agent (orchestrator pattern): it's
	// reaped automatically (on exit/TTL/parent-removal/revoke) and counts against
	// the island's spawn budget. SpawnedBy is the id of the agent that spawned it
	// (lineage; "" for operator-created agents). Co-located sub-agents share this
	// island's sandbox — they are NOT isolated from the parent.
	Ephemeral bool   `toml:"ephemeral,omitempty"`
	SpawnedBy string `toml:"spawned_by,omitempty"`
	// CreatedAt has no omitempty: go-toml/v2 omits a non-zero time.Time under
	// omitempty, which silently dropped this field on every save — so it must be
	// written unconditionally. The spawn reaper's TTL check depends on it surviving
	// a daemon reload.
	CreatedAt time.Time `toml:"created_at"`
}

AgentSpec is one agent running inside an island. An island hosts one or more agents; the first is the "primary" (the attach target for legacy clients).

func (AgentSpec) RefID added in v0.6.9

func (a AgentSpec) RefID() string

RefID / RefLabel let an AgentSpec be used directly as an AgentRef.

func (AgentSpec) RefLabel added in v0.6.9

func (a AgentSpec) RefLabel() string

type CapabilityGrant

type CapabilityGrant struct {
	Target    string    `toml:"target"`
	GrantedAt time.Time `toml:"granted_at"`
}

CapabilityGrant is an island's permission to invoke one named host capability target — a macOS Shortcut, or an executable in ~/.dejima/capabilities/ on Linux. Deny-all is the default: an island may invoke only the targets granted here. The adapter that runs a target is chosen by host OS at execution time, not stored per grant. See docs/capability-broker-spec.md.

type HostGitHubGrant added in v0.8.66

type HostGitHubGrant struct {
	GrantedAt time.Time `toml:"granted_at"`
	// GrantedBy is the actor label from the API identity, when known. Empty for
	// the trusted local socket (the host operator, unauthenticated by design).
	GrantedBy string `toml:"granted_by,omitempty"`
	// Grandfathered marks a grant written by the deny-by-default migration
	// rather than chosen by an operator. It behaves identically — the point is
	// that it can be TOLD APART, so "islands still carrying the old inherited
	// credential" is a question with an answer, and so surfaces can nag about it
	// without nagging about deliberate grants.
	Grandfathered bool `toml:"grandfathered,omitempty"`
}

HostGitHubGrant records a decision to let one island use the HOST operator's own ~/.config/gh. Its presence IS the grant; nil means denied.

type Identity added in v0.6.0

type Identity struct {
	Color string `toml:"color,omitempty"`
	Glyph string `toml:"glyph,omitempty"`
}

Identity is a per-island visual override: a hex color (#rgb or #rrggbb) and a single-rune glyph. The zero value (both empty) means unset. Validation lives in the api layer (PUT /v1/islands/{name}/identity); project stays a pure data struct.

func (Identity) IsSet added in v0.6.0

func (i Identity) IsSet() bool

IsSet reports whether this island carries a visual-identity override (both color and glyph present).

type MCPGrant

type MCPGrant struct {
	Server    string    `toml:"server"`
	GrantedAt time.Time `toml:"granted_at"`
}

MCPGrant is an island's permission to invoke one named, host-curated MCP server (an entry in ~/.dejima/mcp/servers.toml — see internal/mcpbroker). The transport and command behind the name are chosen host-side, not stored per grant; the grant is only the island↦server-name permission.

func AddMCPGrant

func AddMCPGrant(island string, g MCPGrant) (MCPGrant, error)

AddMCPGrant records a grant, rejecting a duplicate server name. The server name is validated by the caller (mcpbroker.ValidateServerName).

func MCPGrantByServer

func MCPGrantByServer(island, server string) (MCPGrant, bool, error)

MCPGrantByServer returns the grant for server, or ok=false.

func MCPGrantsFor

func MCPGrantsFor(island string) ([]MCPGrant, error)

MCPGrantsFor returns an island's MCP-server grants (empty ⇒ deny-all). A missing sidecar is the deny-all default, not an error.

func RemoveMCPGrant

func RemoveMCPGrant(island, server string) (MCPGrant, bool, error)

RemoveMCPGrant drops the grant for server; ok=false if not present.

type PortScope

type PortScope struct {
	// Name is the short, slug handle used to address the scope in Trades and the
	// Ledger (e.g. "vault"). Derived from the host path's basename; unique within
	// the island.
	Name string `toml:"name"`
	// HostPath is the absolute host directory granted. The broker never serves
	// anything outside it.
	HostPath string `toml:"host_path"`
	// Mode is "ro" or "rw".
	Mode      string    `toml:"mode"`
	GrantedAt time.Time `toml:"granted_at"`
}

PortScope is a single brokered host-filesystem grant for an island: a host directory the Port broker may Trade files from/to, and the policy on it.

Access is deny-all by default — an island reaches host content only through an explicit scope. Scopes live in the island's host-side config (0600) and are never writable from inside the island, so an island cannot widen its own grant.

type Project

type Project struct {
	Name string `toml:"name"`
	// Title is a cosmetic, freely-editable display name. Name stays the durable
	// infra handle (container/volume/network/config-dir identity, and the slug
	// addressed by the CLI); Title is what the user reads. Empty → show Name.
	Title   string `toml:"title,omitempty"`
	RepoURL string `toml:"repo"`
	// NoRepo records that this island was created deliberately WITHOUT a repo:
	// an empty /workspace and no origin. It exists so every surface that assumes
	// a checkout can tell "there is no repo, by design" apart from "the clone
	// hasn't finished, or failed" — an empty RepoURL alone cannot, and reading it
	// as a failure is what makes a working island look broken (a workspace-ready
	// poll that never succeeds, a git pane that reports an error, a purge guard
	// that can't verify work it was never given).
	NoRepo bool `toml:"no_repo,omitempty"`
	// Agent and Cmd are the pre-multi-agent scalar fields. They are retained for
	// backward compatibility (older daemons read them) and mirror Agents[0]. New
	// code should read Agents; PrimaryAgent() is the accessor.
	Agent string `toml:"agent"`
	Image string `toml:"image"`
	// Cmd is the command to run inside the island when Agent is "headless".
	// It is ignored for the built-in CLI agents (claude-code, codex), which
	// have a baked-in command. Persisted so reset/reprovision can reuse it.
	Cmd          string      `toml:"cmd,omitempty"`
	Resources    Resources   `toml:"resources,omitempty"`
	CreatedAt    time.Time   `toml:"created_at"`
	LastUsedAt   time.Time   `toml:"last_used_at"`
	DesiredState State       `toml:"state"`
	Agents       []AgentSpec `toml:"agents,omitempty"`
	// NoHibernate pins the island awake: when true it is exempt from idle
	// auto-hibernate (it can still be hibernated manually). For a persistent
	// ambient agent — a watchtower / monitor that must keep running between bursts
	// of work — so an idle window doesn't shut it off. Default false.
	NoHibernate bool `toml:"no_hibernate,omitempty"`
	// Schedules are durable per-island scheduled wakes (see schedule.go). The
	// daemon's scheduler fires each when due, waking the island (and optionally
	// running a task) — surviving restart and `dejima upgrade`.
	Schedules []WakeSchedule `toml:"schedules,omitempty"`
	// Role is the island's purpose: "" (a work island) or "home" (a Home Island
	// hosting an assistant brain). Empty for islands created before roles existed.
	Role string `toml:"role,omitempty"`
	// GitHubIdentity names which of the daemon's GitHub identities this island
	// clones and pushes as (see internal/githubid). Empty means the daemon's
	// default identity, or — when the store is empty — the host's ~/.config/gh.
	GitHubIdentity string `toml:"github_identity,omitempty"`
	// Ports are brokered host-filesystem grants for this island (see ports.go).
	// Empty means deny-all: the island reaches no host content outside its repo.
	Ports []PortScope `toml:"ports,omitempty"`
	// Capabilities are brokered host-action grants for this island (see
	// capabilities.go and docs/capability-broker-spec.md). Empty means deny-all:
	// the island may invoke no host capabilities.
	Capabilities []CapabilityGrant `toml:"capabilities,omitempty"`
	// LinkActions are the named, typed action types THIS island exposes for
	// cross-island delegation (Lane 5, Phase 3). Another island may invoke one of
	// these only if it ALSO holds a link grant authorizing it (or an operator
	// approves ad hoc). Empty means deny-all: this island exposes no actions.
	LinkActions []string `toml:"link_actions,omitempty"`
	// Owner is a free-form creator label (e.g. "alice@laptop"), captured at
	// create time. Purely informational — there is no auth model yet — but it
	// lets wrapper dashboards attribute islands per person/team. Empty for
	// islands created before ownership existed.
	Owner string `toml:"owner,omitempty"`
	// Tags are free-form key=value labels (e.g. team=web, env=staging) for
	// grouping and per-team rollups in wrapper tooling. Empty when untagged.
	Tags map[string]string `toml:"tags,omitempty"`
	// BuiltVersion is the daemon version (version.Version) this island's container
	// was first created against, and UpgradedVersion is the version of the most
	// recent `dejima upgrade` recreate. They are the version-skew stamp: an island
	// whose UpgradedVersion (falling back to BuiltVersion) is behind the running
	// daemon was built from an older image and may carry stale /opt shims (the
	// socket→TCP heartbeat-break class of bug). The api layer sets these from
	// version.Version at create/upgrade; project stays a pure data struct. Empty
	// for islands created before this stamp existed ("unknown" provenance).
	BuiltVersion    string `toml:"built_version,omitempty"`
	UpgradedVersion string `toml:"upgraded_version,omitempty"`
	// Identity is the operator-chosen visual identity (color + glyph) override for
	// this island, persisted in config.toml. Nil/zero means no override — the TUI
	// then falls back to its deterministic per-name default. Set/cleared by the
	// operator via PUT/DELETE /v1/islands/{name}/identity. Cosmetic only.
	Identity Identity `toml:"identity,omitempty"`
	// HostGitHubGrant, when set, lets this island mount the HOST operator's own
	// ~/.config/gh — a credential whose read scope is the operator's entire
	// account. Nil means denied, which is the default for every island created
	// under the grant model. See github_host.go.
	HostGitHubGrant *HostGitHubGrant `toml:"host_github_grant,omitempty"`
	// HostGitHubReviewed records that the deny-by-default decision has been made
	// for this island — by creation under the grant model, by an operator
	// grant/revoke, or by the one-time migration. It is what stops a revoke from
	// being undone by re-grandfathering on the next Load.
	HostGitHubReviewed bool `toml:"host_github_reviewed,omitempty"`
}

Project is the persisted record for a single island.

func List

func List() ([]*Project, error)

List returns every project the daemon knows about.

func Load

func Load(name string) (*Project, error)

Load reads an existing project by name.

func (*Project) AddAgent

func (p *Project) AddAgent(spec AgentSpec)

AddAgent appends an agent to the island.

func (*Project) AddCapabilityGrant

func (p *Project) AddCapabilityGrant(g CapabilityGrant) (CapabilityGrant, error)

AddCapabilityGrant records a grant, rejecting a duplicate target. The target is validated by the caller (see ValidateCapabilityTarget).

func (*Project) AddLinkAction

func (p *Project) AddLinkAction(action string) bool

AddLinkAction exposes action (idempotent). Returns false if already exposed.

func (*Project) AddPortScope

func (p *Project) AddPortScope(s PortScope) (PortScope, error)

AddPortScope cleans the host path, assigns a unique Name, and appends the scope. It errors if the host path is already granted. Returns the stored scope (with its assigned Name).

func (*Project) AddSchedule added in v0.8.3

func (p *Project) AddSchedule(s WakeSchedule) WakeSchedule

AddSchedule appends s (assigning an id if empty) and returns the stored value.

func (*Project) AgentByID

func (p *Project) AgentByID(id string) (*AgentSpec, bool)

AgentByID returns the agent with the given id.

func (*Project) BackfillAgentLabels added in v0.6.9

func (p *Project) BackfillAgentLabels() (changed bool)

BackfillAgentLabels assigns a derived default label to every agent whose Label is blank (empty or all-whitespace), so islands created before default labels existed get readable names with no manual step. It is:

  • idempotent: agents that already have a label are left untouched, so a second run is a no-op (it never re-derives or appends "-2" to a settled label);
  • order-stable: it walks Agents in slice order and derives each label against the labels already present (including ones it just assigned), so the same island always yields the same names; and
  • collision-safe within the island: two blank "claude-code" agents become "claude" and "claude-2", never two "claude".

It mutates in place and returns whether it changed anything, so callers can persist (Save) only when needed and avoid a write storm on already-backfilled islands.

func (*Project) CapabilityGrantByTarget

func (p *Project) CapabilityGrantByTarget(target string) (CapabilityGrant, bool)

CapabilityGrantByTarget returns the grant for target, or ok=false.

func (*Project) ContainerName

func (p *Project) ContainerName() string

ContainerName returns the deterministic container name for this project.

func (*Project) DefaultAgentLabel added in v0.6.9

func (p *Project) DefaultAgentLabel(spec AgentSpec, excludeID string) string

DefaultAgentLabel derives the unique, non-blank label an agent should get when it is created (or backfilled) WITHOUT an explicit label. It maps the agent's Type to a readable base (e.g. "claude-code" → "claude", unknown → "agent") and runs that base through UniqueAgentLabel so the stored default never collides with an existing agent ("claude", "claude-2", …). It NEVER returns blank. exclude lets a caller ignore one agent (e.g. the one being (re)labeled) when checking for collisions; pass "" at create time.

func (*Project) DisplayName

func (p *Project) DisplayName() string

DisplayName is the user-facing name: the Title if set, else the Name slug.

func (*Project) EnsureAgents

func (p *Project) EnsureAgents()

EnsureAgents back-fills Agents from the legacy scalar Agent field for projects persisted under the pre-multi-agent schema. Idempotent: a no-op once Agents is populated. Called on Load and at provision time.

func (*Project) ExposesAction

func (p *Project) ExposesAction(action string) bool

ExposesAction reports whether this island exposes the named action type for cross-island delegation (Lane 5, Phase 3). Deny-all: an unexposed action can never be invoked, even with a link grant.

func (*Project) GrantHostGitHub added in v0.8.66

func (p *Project) GrantHostGitHub(by string, now time.Time) *HostGitHubGrant

GrantHostGitHub records an explicit operator grant, replacing any existing one (which also clears the Grandfathered marker — an operator re-granting is a deliberate decision, and should stop being reported as leftover migration state). Returns the stored grant.

func (*Project) HomeVolume

func (p *Project) HomeVolume() string

HomeVolume returns the per-island home-state volume, mounted at /home/dejima and shared by every agent in the island. Persisting the whole home means tool auth set once by any agent (Claude/Codex creds, ~/.npmrc, gh, eas/expo) survives restarts and is shared — the "collective permissioning" goal.

func (*Project) HostGitHubAllowed added in v0.8.66

func (p *Project) HostGitHubAllowed() bool

HostGitHubAllowed reports whether this island may mount the host operator's own gh credential. Deny-by-default: no grant, no credential.

func (*Project) IsHome

func (p *Project) IsHome() bool

IsHome reports whether this island is a Home Island (hosts an assistant brain).

func (*Project) IsHostOwned added in v0.8.66

func (p *Project) IsHostOwned() bool

IsHostOwned reports whether this island belongs to the host operator rather than a tenant. Ownership is backfilled on Load, so an empty owner only occurs on a Project that hasn't been through it yet.

func (*Project) MoveAgent added in v0.6.0

func (p *Project) MoveAgent(id string, delta int) bool

MoveAgent shifts the agent with the given id by delta positions within the list (negative = toward the front), clamping to the ends. Reports whether the agent was found and actually moved. Order is cosmetic — the dashboard and CLI no longer key off position — except that Agents[0] still seeds the container entrypoint on the next recreate (see docs/island-pid1-unification.md).

func (*Project) NetworkName

func (p *Project) NetworkName() string

NetworkName returns the per-island Docker network name.

func (*Project) NextAgentID

func (p *Project) NextAgentID() string

NextAgentID returns the next monotonic "<letter><N>" id not currently in use. The letter is the island's mnemonic prefix (see agentIDPrefix), so an island named "Port" yields p1, p2, …. Ids are scoped per island and never reused within an island's life, so a removed agent's id stays retired. Numbering is monotonic across whatever prefixes already exist, so a legacy island that holds a1/a2 simply continues at the new prefix (p3).

func (*Project) NextScheduleID added in v0.8.3

func (p *Project) NextScheduleID() string

NextScheduleID returns an island-unique schedule id ("sched-1", "sched-2", …), mirroring NextAgentID.

func (*Project) PortScopeByHostPath

func (p *Project) PortScopeByHostPath(hostPath string) (*PortScope, bool)

PortScopeByHostPath returns the scope for the given (cleaned) host path.

func (*Project) PortScopeByName

func (p *Project) PortScopeByName(name string) (*PortScope, bool)

PortScopeByName returns the scope with the given handle.

func (*Project) PrimaryAgent

func (p *Project) PrimaryAgent() *AgentSpec

PrimaryAgent returns the island's first/primary agent (the attach target for legacy clients), or nil if the island has no agents.

func (*Project) RemoveAgent

func (p *Project) RemoveAgent(id string) bool

RemoveAgent drops the agent with the given id. Reports whether it was found.

func (*Project) RemoveCapabilityGrant

func (p *Project) RemoveCapabilityGrant(target string) (CapabilityGrant, bool)

RemoveCapabilityGrant removes the grant for target; ok=false if not present.

func (*Project) RemoveLinkAction

func (p *Project) RemoveLinkAction(action string) bool

RemoveLinkAction unexposes action. Returns false if it wasn't exposed.

func (*Project) RemovePortScope

func (p *Project) RemovePortScope(key string) (PortScope, bool)

RemovePortScope drops the scope identified by key, which may be either its Name or its (cleaned) host path. Reports the removed scope and whether found.

func (*Project) RemoveSchedule added in v0.8.3

func (p *Project) RemoveSchedule(id string) bool

RemoveSchedule drops the schedule with the given id, reporting whether one was found and removed.

func (*Project) ResolveAgentRef added in v0.6.9

func (p *Project) ResolveAgentRef(ref string) (*AgentSpec, error)

ResolveAgentRef resolves a user-supplied ref (an id or a label) against this island's agents and returns the matching AgentSpec. See the package-level ResolveAgentRef for the resolution rules (id-wins, case-insensitive label, ambiguity and no-match errors).

func (*Project) RevokeHostGitHub added in v0.8.66

func (p *Project) RevokeHostGitHub() (*HostGitHubGrant, bool)

RevokeHostGitHub drops the grant. Returns the removed grant and whether there was one. The island keeps working; it just falls back to having no GitHub credential, which surfaces the same way it does for a tenant island.

func (*Project) Save

func (p *Project) Save() error

Save writes the project config to disk.

func (*Project) SetPrimaryID

func (p *Project) SetPrimaryID(id string)

SetPrimaryID renames the primary agent's id and the tmux session derived from it. Intended for fresh provision only — before any container or session exists — so it deliberately does not migrate a running session.

func (*Project) StampVersion added in v0.6.0

func (p *Project) StampVersion() string

StampVersion returns the most authoritative version this island was last built or upgraded against: the upgrade stamp if present, else the build stamp. Empty when the island predates version stamping (provenance unknown).

func (*Project) UniqueAgentLabel added in v0.6.7

func (p *Project) UniqueAgentLabel(desired, excludeID string) string

UniqueAgentLabel returns a label not in use by any existing agent in this island, deduping case-insensitively on the trimmed value. If desired is empty (or all whitespace) it is returned as-is — empty labels are allowed and never deduped. Otherwise, on a collision it appends "-2", "-3", … skipping any variant already taken ("build" → "build-2" → "build-3"), mirroring the spirit of NextAgentID. exclude lets a rename ignore the agent being renamed so renaming to its own current label is a no-op (not "build-2"); pass "" at create time when there is nothing to exclude.

func (*Project) WorkspaceVolume

func (p *Project) WorkspaceVolume() string

WorkspaceVolume returns the workspace volume name.

type Resources

type Resources struct {
	Memory string `toml:"memory,omitempty"` // e.g. "4G"
	CPUs   string `toml:"cpus,omitempty"`   // e.g. "2.0"
	Disk   string `toml:"disk,omitempty"`   // e.g. "20G" — maps to --storage-opt size=
	// OOMPriority stack-ranks islands for the kernel OOM killer: higher = more
	// protected (killed later). nil = unset → resolved to a smart default at
	// create (headless brains start expendable). Mapped to docker --oom-score-adj
	// (inverted) in the api layer. Set-at-create only; a change needs a recreate.
	OOMPriority *int `toml:"oom_priority,omitempty"`
}

Resources captures the docker resource caps applied to the container. All fields optional; zero/empty means unlimited.

type State

type State string

State is the desired state of an island.

const (
	StateRunning    State = "running"
	StateHibernated State = "hibernated"
)

type WakeSchedule added in v0.8.3

type WakeSchedule struct {
	ID string `toml:"id"`
	// Every is a Go duration string ("720h") for a recurring wake; "" = one-shot.
	Every string `toml:"every,omitempty"`
	// Task is an optional prompt/command injected into the agent on wake; "" just
	// wakes the island (what then runs is the agent's own business).
	Task string `toml:"task,omitempty"`
	// Agent selects which agent runs Task (id or label); "" = the island's primary.
	Agent string `toml:"agent,omitempty"`
	// NextDue is when the scheduler should next fire this (UTC).
	NextDue time.Time `toml:"next_due"`
	// LastRun is the last time it fired (UTC); zero until the first fire. No
	// omitempty: go-toml/v2's omitempty drops a non-zero time.Time, which would
	// silently lose the last-run stamp across a save/load.
	LastRun   time.Time `toml:"last_run"`
	CreatedAt time.Time `toml:"created_at"`
}

WakeSchedule is a durable, daemon-owned instruction to wake an island on a cadence (or once), optionally running a task on the agent. Stored in the island's config.toml so it survives daemon restart AND `dejima upgrade` — the whole point versus an in-island cron, which dies on container recreate.

func (*WakeSchedule) AdvanceAfterFire added in v0.8.3

func (w *WakeSchedule) AdvanceAfterFire(now time.Time) bool

AdvanceAfterFire moves a recurring schedule's NextDue forward FROM now (catch-up, not stack: anchor to now+Every rather than replaying every missed interval). Returns false for a one-shot — the caller deletes it after firing.

func (WakeSchedule) Due added in v0.8.3

func (w WakeSchedule) Due(now time.Time) bool

Due reports whether the schedule should fire at now.

func (WakeSchedule) EveryDuration added in v0.8.3

func (w WakeSchedule) EveryDuration() (time.Duration, bool)

EveryDuration parses Every into a positive duration; ok=false for a one-shot (empty or unparseable Every).

func (WakeSchedule) Recurring added in v0.8.3

func (w WakeSchedule) Recurring() bool

Recurring reports whether this schedule repeats.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL