Skip to content

Commit 4629799

Browse files
authored
Merge pull request #956 from rumpl/oci-source
OCI source
2 parents 0e9d4f5 + 6d0d50a commit 4629799

11 files changed

Lines changed: 268 additions & 1822 deletions

File tree

cmd/root/api.go

Lines changed: 4 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,14 @@ import (
44
"fmt"
55
"log/slog"
66
"os"
7-
"path/filepath"
8-
"time"
97

108
"github.com/spf13/cobra"
119

1210
"github.com/docker/cagent/pkg/agentfile"
1311
"github.com/docker/cagent/pkg/cli"
1412
"github.com/docker/cagent/pkg/config"
15-
"github.com/docker/cagent/pkg/remote"
1613
"github.com/docker/cagent/pkg/server"
1714
"github.com/docker/cagent/pkg/session"
18-
"github.com/docker/cagent/pkg/teamloader"
1915
"github.com/docker/cagent/pkg/telemetry"
2016
)
2117

@@ -73,96 +69,21 @@ func (f *apiFlags) runAPICommand(cmd *cobra.Command, args []string) error {
7369

7470
slog.Debug("Starting server", "agents", agentsPath, "addr", ln.Addr().String())
7571

76-
resolvedPath, err := agentfile.Resolve(ctx, out, agentsPath)
77-
if err != nil {
78-
return err
79-
}
80-
8172
sessionStore, err := session.NewSQLiteSessionStore(f.sessionDB)
8273
if err != nil {
8374
return fmt.Errorf("failed to create session store: %w", err)
8475
}
8576

86-
var opts []server.Opt
87-
88-
if !agentfile.IsOCIReference(agentsPath) {
89-
stat, err := os.Stat(resolvedPath)
90-
if err != nil {
91-
return fmt.Errorf("failed to stat agents path: %w", err)
92-
}
93-
if stat.IsDir() {
94-
// For directories: only set agentsDir, not agentsPath
95-
opts = append(opts, server.WithAgentsDir(resolvedPath))
96-
} else {
97-
opts = append(opts, server.WithAgentsPath(resolvedPath), server.WithAgentsDir(filepath.Dir(resolvedPath)))
98-
}
99-
}
100-
101-
teams, err := teamloader.LoadTeams(ctx, resolvedPath, &f.runConfig)
77+
sources, err := agentfile.ResolveSources(ctx, nil, agentsPath)
10278
if err != nil {
103-
return fmt.Errorf("failed to load teams: %w", err)
104-
}
105-
106-
// For OCI refs: store the reference for later per-session reloading, then clean up temp file
107-
if agentfile.IsOCIReference(agentsPath) {
108-
teamKey := filepath.Base(resolvedPath)
109-
opts = append(opts, server.WithOCIRef(teamKey, agentsPath))
110-
111-
if err := os.Remove(resolvedPath); err != nil {
112-
slog.Warn("Failed to remove temporary OCI file", "path", resolvedPath, "error", err)
113-
} else {
114-
slog.Debug("Cleaned up temporary OCI file", "path", resolvedPath)
115-
}
79+
return fmt.Errorf("failed to resolve agent sources: %w", err)
11680
}
117-
118-
defer func() {
119-
for _, team := range teams {
120-
if err := team.StopToolSets(ctx); err != nil {
121-
slog.Error("Failed to stop tool sets", "error", err)
122-
}
123-
}
124-
}()
125-
126-
s, err := server.New(sessionStore, &f.runConfig, teams, opts...)
81+
s, err := server.New(sessionStore, &f.runConfig, sources)
12782
if err != nil {
12883
return fmt.Errorf("failed to create server: %w", err)
12984
}
13085

131-
// Start background auto-pull for OCI references if enabled
132-
if f.pullIntervalMins > 0 {
133-
go func() {
134-
ticker := time.NewTicker(time.Duration(f.pullIntervalMins) * time.Minute)
135-
defer ticker.Stop()
136-
137-
slog.Info("Auto-pull enabled for OCI reference", "reference", agentsPath, "interval_minutes", f.pullIntervalMins)
138-
139-
for {
140-
select {
141-
case <-ctx.Done():
142-
return
143-
case <-ticker.C:
144-
slog.Info("Auto-pulling OCI reference", "reference", agentsPath)
145-
if _, err := remote.Pull(ctx, agentsPath, false); err != nil {
146-
slog.Error("Failed to auto-pull OCI reference", "reference", agentsPath, "error", err)
147-
continue
148-
}
149-
150-
// Resolve the OCI reference to get the updated file path
151-
newResolvedPath, err := agentfile.Resolve(ctx, out, agentsPath)
152-
if err != nil {
153-
slog.Error("Failed to resolve OCI reference after pull", "reference", agentsPath, "error", err)
154-
continue
155-
}
156-
157-
if err := s.ReloadTeams(ctx, newResolvedPath); err != nil {
158-
slog.Error("Failed to reload teams", "reference", agentsPath, "error", err)
159-
} else {
160-
slog.Info("Successfully reloaded teams from updated OCI reference", "reference", agentsPath)
161-
}
162-
}
163-
}
164-
}()
165-
}
86+
// TODO(rumpl): implement pull interval
16687

16788
return s.Serve(ctx, ln)
16889
}

cmd/root/pull.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99
"github.com/google/go-containerregistry/pkg/crane"
1010
"github.com/spf13/cobra"
1111

12-
"github.com/docker/cagent/pkg/agentfile"
1312
"github.com/docker/cagent/pkg/cli"
13+
"github.com/docker/cagent/pkg/content"
1414
"github.com/docker/cagent/pkg/remote"
1515
"github.com/docker/cagent/pkg/telemetry"
1616
)
@@ -52,7 +52,11 @@ func (f *pullFlags) runPullCommand(cmd *cobra.Command, args []string) error {
5252
return fmt.Errorf("failed to pull artifact: %w", err)
5353
}
5454

55-
yamlFile, err := agentfile.FromStore(registryRef)
55+
store, err := content.NewStore()
56+
if err != nil {
57+
return fmt.Errorf("failed to open content store: %w", err)
58+
}
59+
yamlFile, err := store.GetArtifact(registryRef)
5660
if err != nil {
5761
return fmt.Errorf("failed to get agent yaml: %w", err)
5862
}

pkg/acp/agent.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
type Agent struct {
2323
conn *acp.AgentSideConnection
2424
team *team.Team
25-
agentFilename string
25+
source teamloader.AgentSource
2626
runtimeConfig *config.RuntimeConfig
2727
sessions map[string]*Session
2828
mu sync.Mutex
@@ -39,9 +39,9 @@ type Session struct {
3939
}
4040

4141
// NewAgent creates a new ACP agent
42-
func NewAgent(agentFilename string, runtimeConfig *config.RuntimeConfig) *Agent {
42+
func NewAgent(source teamloader.AgentSource, runtimeConfig *config.RuntimeConfig) *Agent {
4343
return &Agent{
44-
agentFilename: agentFilename,
44+
source: source,
4545
runtimeConfig: runtimeConfig,
4646
sessions: make(map[string]*Session),
4747
}
@@ -69,7 +69,7 @@ func (a *Agent) Initialize(ctx context.Context, params acp.InitializeRequest) (a
6969

7070
a.mu.Lock()
7171
defer a.mu.Unlock()
72-
t, err := teamloader.Load(ctx, a.agentFilename, a.runtimeConfig, teamloader.WithToolsetRegistry(createToolsetRegistry(a)))
72+
t, err := teamloader.LoadFrom(ctx, a.source, a.runtimeConfig, teamloader.WithToolsetRegistry(createToolsetRegistry(a)))
7373
if err != nil {
7474
return acp.InitializeResponse{}, fmt.Errorf("failed to load teams: %w", err)
7575
}

pkg/acp/run.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,15 @@ import (
1111
"github.com/docker/cagent/pkg/config"
1212
)
1313

14-
type discardOutput struct{}
15-
16-
func (d *discardOutput) Printf(string, ...any) {}
17-
1814
func Run(ctx context.Context, agentFilename string, stdin io.Reader, stdout io.Writer, runConfig *config.RuntimeConfig) error {
1915
slog.Debug("Starting ACP server", "agent", agentFilename)
2016

21-
agentFilename, err := agentfile.Resolve(ctx, &discardOutput{}, agentFilename)
17+
source, err := agentfile.ResolveSource(ctx, nil, agentFilename)
2218
if err != nil {
2319
return err
2420
}
2521

26-
acpAgent := NewAgent(agentFilename, runConfig)
22+
acpAgent := NewAgent(source, runConfig)
2723
conn := acpsdk.NewAgentSideConnection(acpAgent, stdout, stdin)
2824
conn.SetLogger(slog.Default())
2925
acpAgent.SetAgentConnection(conn)

0 commit comments

Comments
 (0)