Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions go/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
dappco.re/go v0.12.0
dappco.re/go/api v0.19.0
dappco.re/go/cli v0.13.0
dappco.re/go/container v0.12.0
dappco.re/go/container v0.13.0
dappco.re/go/io v0.15.3
dappco.re/go/mcp v0.19.1
dappco.re/go/orm v0.1.2
Expand Down Expand Up @@ -63,7 +63,7 @@ require (
github.com/duckdb/duckdb-go-bindings/lib/linux-arm64 v0.10505.0 // indirect
github.com/duckdb/duckdb-go-bindings/lib/windows-amd64 v0.10505.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/ebitengine/purego v0.10.1 // indirect
github.com/ebitengine/purego v0.10.2 // indirect
github.com/gabriel-vasile/mimetype v1.4.15 // indirect
github.com/gin-contrib/authz v1.0.7 // indirect
github.com/gin-contrib/cors v1.7.7 // indirect
Expand Down Expand Up @@ -126,7 +126,7 @@ require (
github.com/swaggo/files v1.0.1 // indirect
github.com/swaggo/gin-swagger v1.6.1 // indirect
github.com/swaggo/swag v1.16.6 // indirect
github.com/tmc/apple v0.6.12 // indirect
github.com/tmc/apple v0.6.15 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.3.1 // indirect
github.com/vektah/gqlparser/v2 v2.5.36 // indirect
Expand Down
20 changes: 10 additions & 10 deletions go/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ dappco.re/go/api v0.19.0 h1:vhkSRaUpDEz7Jm8tWbwWHvz1f4+TiO82JK8Pytv/sEk=
dappco.re/go/api v0.19.0/go.mod h1:Q0IEARpCTgQjOU6eGZTG2jq0WLI4GJ+eCt+Ys3n/hxg=
dappco.re/go/cli v0.13.0 h1:vDp6eA3ojR6VrPPLn9aE/P4gvB4zABZ4flATsx/QsAs=
dappco.re/go/cli v0.13.0/go.mod h1:0T0UcDGQIr1wIAcUs87oGlFD32aAl45bo834MHy47K8=
dappco.re/go/container v0.12.0 h1:MZRDoohrwEOtJBJmjUNrf3XvgSvA8Ytfgpn0F/Ves2s=
dappco.re/go/container v0.12.0/go.mod h1:2kFV8kWjcZXefWHjnIHBNXxM28nfpb7yIfJACJ2/hxs=
dappco.re/go/container v0.13.0 h1:TBFjJk+1btm7duvYS7n9wLxQIjVokAFnkh1QWhBfljQ=
dappco.re/go/container v0.13.0/go.mod h1:aR0YoWs2IBt8yePouttXXa6oHutHvpGqY7nJMOpYT/Q=
dappco.re/go/i18n v0.12.1 h1:Pm1DF9I0O8bckTr815OrnR+G+7EvbQhP2Vk4ItC0mB4=
dappco.re/go/i18n v0.12.1/go.mod h1:AYx1QkPfW+qvzLCfJnuOlc4J+grwlgFzoHnoke4TAYg=
dappco.re/go/io v0.15.3 h1:cG+pHjzi1jja99rPRiTG3DYFxQ9XUognHr8rNrPofGg=
Expand All @@ -32,8 +32,8 @@ github.com/99designs/gqlgen v0.17.94 h1:+3EUDVgX/8gDyDL+7NUqCo4cy2ylylwW0GvR1dGi
github.com/99designs/gqlgen v0.17.94/go.mod h1:o+XaAMpPA/AX4rqeiK03tZUb/5T+WCgpRDD4aujgdas=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw=
github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE=
github.com/ProtonMail/go-crypto v1.4.1 h1:9RfcZHqEQUvP8RzecWEUafnZVtEvrBVL9BiF67IQOfM=
github.com/ProtonMail/go-crypto v1.4.1/go.mod h1:e1OaTyu5SYVrO9gKOEhTc+5UcXtTUa+P3uLudwcgPqo=
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/Snider/Poindexter v0.1.0 h1:lZ94xfjiFcBK2zaEQWhyW8HKZ2KS9xTRiVfVCERj9w8=
github.com/Snider/Poindexter v0.1.0/go.mod h1:nhgkbg4zWA4AS2Ga3RmcvdsyiI9TdxvSqe5EVBSb3Hk=
Expand Down Expand Up @@ -98,8 +98,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
github.com/cloudflare/circl v1.6.4 h1:pOXuDTCEYyzydgUpQ0CQz3LsinKjiSk6nNP5Lt5K64U=
github.com/cloudflare/circl v1.6.4/go.mod h1:YxarevkLlbaHuWsxG6vmYNWBEsSp4pnp7j+4VljMavY=
github.com/cloudwego/base64x v0.1.7 h1:NppS+Fgzg5ovhn4NkUXaDT3x9jldgH5ToMCqzBSi2zI=
github.com/cloudwego/base64x v0.1.7/go.mod h1:Cu1PV9zfrSf7ET2tIbWbbEy7jO7HHJ13q4X2SQ8aWYg=
github.com/coder/websocket v1.8.15 h1:6B2JPeOGlpff2Uz6vOEH1Vzpi0iUz20A+lPVhPHtNUA=
Expand Down Expand Up @@ -128,8 +128,8 @@ github.com/duckdb/duckdb-go/v2 v2.10505.0 h1:SWwvLn2Qx/RQSnQNupwgIF8VbnJ5A6OQU9l
github.com/duckdb/duckdb-go/v2 v2.10505.0/go.mod h1:m0PW4J4FG9hlFlVdXi6Ds9owpyIDaBdE2jyce00fGcE=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/ebitengine/purego v0.10.1 h1:dewVBCBT2GaMu1SrNTYxQhgQBethzfhiwvZiLGP/qyY=
github.com/ebitengine/purego v0.10.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/ebitengine/purego v0.10.2 h1:W809HbnvzAxgdm+aOvlSekrM16wGCdT/e76+9tS7gzE=
github.com/ebitengine/purego v0.10.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/gabriel-vasile/mimetype v1.4.15 h1:05iP/CYtZ/w455R/KZM6rZ5ieAdh99UPtd+d3YzLmaI=
github.com/gabriel-vasile/mimetype v1.4.15/go.mod h1:azpTcoLcDZRNgFou5j+APrqQx9HqVPWa6ijYQIIVswQ=
github.com/gin-contrib/authz v1.0.7 h1:sAKv+rt6U3NwR20MSbzwQYcFGEeUD5I4oC+/sdUsq+Q=
Expand Down Expand Up @@ -326,8 +326,8 @@ github.com/swaggo/gin-swagger v1.6.1 h1:Ri06G4gc9N4t4k8hekMigJ9zKTFSlqj/9paAQCQs
github.com/swaggo/gin-swagger v1.6.1/go.mod h1:LQ+hJStHakCWRiK/YNYtJOu4mR2FP+pxLnILT/qNiTw=
github.com/swaggo/swag v1.16.6 h1:qBNcx53ZaX+M5dxVyTrgQ0PJ/ACK+NzhwcbieTt+9yI=
github.com/swaggo/swag v1.16.6/go.mod h1:ngP2etMK5a0P3QBizic5MEwpRmluJZPHjXcMoj4Xesg=
github.com/tmc/apple v0.6.12 h1:9GPwKjDy2Ngoyq9+6IzGouL6fjgDXc0w6kMF2cRQK9k=
github.com/tmc/apple v0.6.12/go.mod h1:QJV85Y1rc4sDQtuBobmYe4mIz5akPLzm3caYmVEmdvE=
github.com/tmc/apple v0.6.15 h1:tKPf5WPbWTPjx7zD/Gy05DezkDuQGfo26jOxEvhLZDg=
github.com/tmc/apple v0.6.15/go.mod h1:QJV85Y1rc4sDQtuBobmYe4mIz5akPLzm3caYmVEmdvE=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
Expand Down
20 changes: 5 additions & 15 deletions go/pkg/agentic/dispatch_vz.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,9 @@ type vzDispatcher interface {
// Run boots a guest image and returns the running *container.Container.
Run(image *container.Image, opts ...container.RunOption) core.Result
// ExecResult runs a command in the guest over vsock and returns its full
// outcome — Value is a container.ExecResult{Stdout, Stderr, Exit}, which
// vzDecodeExec normalises into vzExec. A command that ran and exited
// non-zero is OK at the verb level (the exit code is preserved); only
// verb-level failures Fail.
// outcome — Value is a container.ExecResult{Stdout, Stderr, Exit}. A command
// that ran and exited non-zero is OK at the verb level (the exit code is
// preserved); only verb-level failures Fail.
ExecResult(id, command string, args ...string) core.Result
// Stop gracefully stops a running guest.
Stop(id string) core.Result
Expand All @@ -101,15 +100,6 @@ type vzDispatcher interface {
// inject a fake; production returns the concrete in-process provider.
var newVZProvider = func() vzDispatcher { return newVZProviderImpl() }

// vzExec is the platform-neutral form of an exec outcome. go-container declares
// ExecResult inside its darwin-tagged vz.go, so naming that type here would
// stop the package building on Linux; vzDecodeExec converts into this instead.
type vzExec struct {
Stdout string
Stderr string
Exit int
}

// vzResolveExec runs the go-build image resolver and returns its core.Result —
// Value is the captured stdout string on success. It is a package var (a seam)
// so unit tests inject a scripted Result instead of shelling out. Production
Expand Down Expand Up @@ -277,7 +267,7 @@ func (v *vzCompletionProcess) run(provider vzDispatcher) {
v.finish(vzExitFailed, process.StatusFailed, vzResultMessage(execResult))
return
}
result, ok := vzDecodeExec(execResult)
result, ok := execResult.Value.(container.ExecResult)
if !ok {
v.finish(vzExitFailed, process.StatusFailed, "vz exec returned unexpected result type")
return
Expand All @@ -295,7 +285,7 @@ func (v *vzCompletionProcess) run(provider vzDispatcher) {
// the completionProcess/monitor contract carries. stdout is the agent's
// captured output; stderr is appended (labelled) only when present so a failed
// run surfaces why without masking the stdout of a successful one.
func vzExecOutput(result vzExec) string {
func vzExecOutput(result container.ExecResult) string {
if result.Stderr == "" {
return result.Stdout
}
Expand Down
6 changes: 3 additions & 3 deletions go/pkg/agentic/dispatch_vz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func TestDispatchVZ_CompletionProcess_Good_ExecStop(t *testing.T) {
// drives only the structured ExecResult→Stop tail.
fake := &fakeVZDispatcher{
available: true,
execResult: core.Ok(vzExec{Stdout: "agent stdout", Exit: 0}),
execResult: core.Ok(container.ExecResult{Stdout: "agent stdout", Exit: 0}),
stopResult: core.Ok(nil),
}
proc := &vzCompletionProcess{
Expand Down Expand Up @@ -209,7 +209,7 @@ func TestDispatchVZ_CompletionProcess_Ugly_NonZeroExitPreserved(t *testing.T) {
// vzExitFailed) and fold stderr into the output for the monitor.
fake := &fakeVZDispatcher{
available: true,
execResult: core.Ok(vzExec{Stdout: "partial", Stderr: "boom", Exit: 2}),
execResult: core.Ok(container.ExecResult{Stdout: "partial", Stderr: "boom", Exit: 2}),
stopResult: core.Ok(nil),
}
proc := &vzCompletionProcess{id: "vz-test", containerID: "vzfake01", command: "false", startedAt: time.Now(), done: make(chan struct{})}
Expand Down Expand Up @@ -242,7 +242,7 @@ func TestDispatchVZ_CompletionDrivesOnAgentComplete_Good_Case(t *testing.T) {

// A real vzCompletionProcess driven by a fake provider — proving the adapter
// satisfies completionProcess AND that the existing monitor consumes it.
fake := &fakeVZDispatcher{available: true, execResult: core.Ok(vzExec{Stdout: "vz output", Exit: 0}), stopResult: core.Ok(nil)}
fake := &fakeVZDispatcher{available: true, execResult: core.Ok(container.ExecResult{Stdout: "vz output", Exit: 0}), stopResult: core.Ok(nil)}
proc := &vzCompletionProcess{id: "vz-ws", containerID: "vzfake01", command: "true", startedAt: time.Now(), done: make(chan struct{})}
proc.run(fake)

Expand Down
32 changes: 4 additions & 28 deletions go/pkg/agentic/vz_platform_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@
package agentic

import (
core "dappco.re/go"
"dappco.re/go/container"
)

// Everything go-container gates behind //go:build darwin is reached through
// this file, so the rest of pkg/agentic compiles on every platform. vz.go in
// dappco.re/go/container carries that constraint, which puts IsVZAvailable,
// NewVZProvider and ExecResult out of reach of a Linux build — the package
// referenced all three unguarded and so failed to build in CI while building
// fine on a developer's Mac.
// The darwin half of the VZ seam. Virtualization.framework is Apple-only, so
// go-container declares IsVZAvailable and NewVZProvider behind //go:build
// darwin in vz.go; reaching them through this file is what keeps the rest of
// pkg/agentic compiling on every platform.

// vzHostAvailable reports whether Virtualization.framework is usable here.
//
Expand All @@ -25,24 +22,3 @@ func vzHostAvailable() bool { return container.IsVZAvailable() }
//
// provider := newVZProviderImpl()
func newVZProviderImpl() vzDispatcher { return container.NewVZProvider() }

// vzDecodeExec normalises an ExecResult verb payload into the platform-neutral
// vzExec the fork works with.
//
// container.ExecResult is checked second so an injected vzExec still decodes:
// the unit tests script the fake dispatcher with vzExec directly rather than
// with a type they cannot name on Linux.
//
// exec, ok := vzDecodeExec(provider.ExecResult(id, "sh", "-c", "true"))
func vzDecodeExec(result core.Result) (vzExec, bool) {
if exec, ok := result.Value.(vzExec); ok {
return exec, true
}

native, ok := result.Value.(container.ExecResult)
if !ok {
return vzExec{}, false
}

return vzExec{Stdout: native.Stdout, Stderr: native.Stderr, Exit: native.Exit}, true
}
14 changes: 0 additions & 14 deletions go/pkg/agentic/vz_platform_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,6 @@ func vzHostAvailable() bool { return false }
// provider := newVZProviderImpl()
func newVZProviderImpl() vzDispatcher { return vzUnsupportedProvider{} }

// vzDecodeExec normalises an ExecResult verb payload into vzExec.
//
// Only the injected form is decodable off darwin: container.ExecResult is
// declared inside go-container's darwin-tagged vz.go and cannot be named here.
// Production never reaches this — vzUnsupportedProvider fails before exec — but
// the unit tests script the fake dispatcher with vzExec and do run on Linux.
//
// exec, ok := vzDecodeExec(core.Ok(vzExec{Stdout: "hi"}))
func vzDecodeExec(result core.Result) (vzExec, bool) {
exec, ok := result.Value.(vzExec)

return exec, ok
}

// vzUnsupportedProvider satisfies vzDispatcher on hosts with no
// Virtualization.framework, failing every verb rather than pretending.
type vzUnsupportedProvider struct{}
Expand Down
Loading