agent/pkg/runner/paths.go
Snider 0fc6eeb4cc feat(runner): extract dispatch runner into independent Core service
Moves concurrency, queue drain, workspace lifecycle, and frozen state
from agentic/prep into pkg/runner/ — a standalone Core service that
communicates via IPC Actions only.

- runner.Register wires Actions: dispatch, status, start, stop, kill, poke
- runner.HandleIPCEvents catches AgentCompleted → ChannelPush + queue poke
- Agentic dispatch asks runner for permission via c.Action("runner.dispatch")
- Dispatch mutex moved to struct-level sync.Mutex (fixes core.Lock init race)
- Registry-based concurrency counting replaces disk scanning
- TrackWorkspace called on both queued and running status writes
- SpawnQueued message added for runner→agentic spawn requests
- ChannelPush message in core/mcp enables any service to push channel events
- 51 new tests covering runner service, queue, and config parsing

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 11:00:47 +00:00

51 lines
1.4 KiB
Go

// SPDX-License-Identifier: EUPL-1.2
package runner
import (
core "dappco.re/go/core"
)
// fs is the file I/O medium for the runner package.
var fs = (&core.Fs{}).NewUnrestricted()
// WorkspaceRoot returns the root directory for agent workspaces.
//
// root := runner.WorkspaceRoot() // ~/Code/.core/workspace
func WorkspaceRoot() string {
return core.JoinPath(CoreRoot(), "workspace")
}
// CoreRoot returns the root directory for core ecosystem files.
//
// root := runner.CoreRoot() // ~/Code/.core
func CoreRoot() string {
if root := core.Env("CORE_WORKSPACE"); root != "" {
return root
}
return core.JoinPath(core.Env("DIR_HOME"), "Code", ".core")
}
// ReadStatus reads a workspace status.json.
//
// st, err := runner.ReadStatus("/path/to/workspace")
func ReadStatus(wsDir string) (*WorkspaceStatus, error) {
path := core.JoinPath(wsDir, "status.json")
r := fs.Read(path)
if !r.OK {
return nil, core.E("runner.ReadStatus", "failed to read status", nil)
}
var st WorkspaceStatus
if result := core.JSONUnmarshalString(r.Value.(string), &st); !result.OK {
return nil, core.E("runner.ReadStatus", "failed to parse status", nil)
}
return &st, nil
}
// WriteStatus writes a workspace status.json.
//
// runner.WriteStatus(wsDir, &runner.WorkspaceStatus{Status: "running", Agent: "codex"})
func WriteStatus(wsDir string, st *WorkspaceStatus) {
path := core.JoinPath(wsDir, "status.json")
fs.Write(path, core.JSONMarshalString(st))
}