Documentation
¶
Overview ¶
Package jobs runs and tracks detached background agent sessions. A job is a child `memcode` process whose output streams to a log file under .memcode/jobs/<id>/; its metadata (task, pid, status) lives beside the log. Background agents are writers, so they coordinate through a single repo-wide writer lock — the "one serialized writer" half of memcode's concurrency model: any number of read-only explorers may run at once, but mutating jobs run one at a time, queueing on the lock rather than clobbering each other's edits.
Index ¶
- Constants
- func AcquireWriter(ctx context.Context, root string) (release func(), err error)
- func Finish(root, id string, exitCode int, result string) error
- func Heartbeat(root, id, activity string, tokensIn, tokensOut int64) error
- func LogPath(root, id string) string
- func Stop(root, id string) error
- type ExecutionBudgets
- type Job
- type ResourceGrant
- type SpawnSpec
- type ToolPolicy
Constants ¶
const ( StatusRunning = "running" StatusWaiting = "waiting" StatusDone = "done" StatusFailed = "failed" StatusStopped = "stopped" // process gone but never recorded a finish )
Status values for a job.
Variables ¶
This section is empty.
Functions ¶
func AcquireWriter ¶
AcquireWriter blocks until this process holds the repo-wide writer lock, then returns a release func. It coordinates background writer jobs so only one mutates the tree at a time; a stale lock (owner process gone) is reclaimed. ctx cancellation aborts the wait.
func Finish ¶
Finish records a job's terminal status (called by the child when it exits). result is the agent's final text, persisted so a report-back job can feed it to the calling LLM.
func Heartbeat ¶ added in v0.27.0
Heartbeat updates a RUNNING job's live activity/token readout. It re-reads the meta immediately before writing and refuses to touch a job that is no longer running, so it can never resurrect (or clobber) a terminal record — if Finish or Stop landed first, their status/result win and the heartbeat is dropped. The child stops heartbeating before it calls Finish, so within the child process the two never interleave.
func Stop ¶
Stop terminates a running job: signals its process (SIGTERM, then SIGKILL if it doesn't exit), and records the job as stopped. Returns an error if the job isn't found or isn't running. This is the safety valve for a runaway detached agent — the TUI/CLI equivalent of /kill for in-session shells.
Types ¶
type ExecutionBudgets ¶ added in v0.28.0
type Job ¶
type Job struct {
ID string `json:"id"`
Task string `json:"task"`
Mode string `json:"mode"`
ReportBack bool `json:"report_back,omitempty"` // true → on finish, feed Result back to the calling LLM (agent{background}), not just the user
Result string `json:"result,omitempty"` // the agent's final text (set by Finish) — what gets reported back
PID int `json:"pid"`
// StartSig is the child process's start-time signature captured at spawn (ps lstart on
// unix; "" where unavailable). PIDs recycle, so before reporting a job as running — and
// especially before SIGNALING its pid — the live process's signature must match: a
// mismatch means the pid now belongs to an unrelated process. Additive field; old metas
// without it keep the plain liveness check.
StartSig string `json:"start_sig,omitempty"`
Status string `json:"status"`
ExitCode int `json:"exit_code"`
StartedAt time.Time `json:"started_at"`
FinishedAt time.Time `json:"finished_at,omitempty"`
// Live readout, heartbeated by the running child (~1s) so frontends can show
// what a detached agent is doing right now. Additive; absent in old metas.
Activity string `json:"activity,omitempty"` // latest tool label, e.g. "bash(go test ./...)"
TokensIn int64 `json:"tokens_in,omitempty"` // child session input tokens so far
TokensOut int64 `json:"tokens_out,omitempty"` // child session output tokens so far
HeartbeatAt time.Time `json:"heartbeat_at,omitempty"`
AgentID string `json:"agent_id,omitempty"`
ObjectiveID string `json:"objective_id,omitempty"`
SubgoalID string `json:"subgoal_id,omitempty"`
RunID string `json:"run_id,omitempty"`
ParentRunID string `json:"parent_run_id,omitempty"`
SessionID string `json:"session_id,omitempty"`
PolicyHash string `json:"policy_hash,omitempty"`
ExecutionEnvelope json.RawMessage `json:"execution_envelope,omitempty"`
}
func List ¶
List returns all jobs, newest first, with live status reconciled (a job recorded as running whose process is gone is reported as stopped).
func Spawn ¶
Spawn launches a detached `memcode run <task>` child, redirecting its output to the job log, and records the job as running. The child is invoked with --job <id> so it acquires the writer lock and records its own completion. When chrome is true, --chrome is forwarded so backgrounded browser jobs keep the capability (Chrome always launches with a visible window).
func SpawnWithSpec ¶ added in v0.28.0
type ResourceGrant ¶ added in v0.28.0
type ResourceGrant struct {
IDs []string `json:"ids,omitempty"`
}
type SpawnSpec ¶ added in v0.28.0
type SpawnSpec struct {
Root, Task, Mode, SessionID, AgentID, ObjectiveID, SubgoalID, RunID, ParentRunID, PolicyHash, BrowserMode string
ToolPolicy ToolPolicy
ResourceGrant ResourceGrant
Budgets ExecutionBudgets
ReportBack bool
}
type ToolPolicy ¶ added in v0.28.0
type ToolPolicy struct {
Allowed []string `json:"allowed,omitempty"`
Disabled []string `json:"disabled,omitempty"`
}
Job is one background agent session.