@@ -110,70 +110,82 @@ func (a ociSource) ParentDir() string {
110110 return ""
111111}
112112
113- // Read loads an agent configuration from an OCI artifact
113+ // Read loads an agent configuration from an OCI artifact.
114114//
115- // The OCI registry remains the source of truth
116- // The local content store is used as a cache and fallback only
117- // A forced re-pull is triggered exclusively when store corruption is detected
115+ // The OCI registry remains the source of truth.
116+ // The local content store is used as a cache and fallback only.
117+ // A forced re-pull is triggered exclusively when store corruption is detected.
118118func (a ociSource ) Read (ctx context.Context ) ([]byte , error ) {
119119 store , err := content .NewStore ()
120120 if err != nil {
121121 return nil , fmt .Errorf ("failed to create content store: %w" , err )
122122 }
123123
124- tryLoad := func () ([]byte , error ) {
125- af , err := store .GetArtifact (a .reference )
126- if err != nil {
127- return nil , err
124+ // Normalize the reference so that equivalent forms (e.g.
125+ // "agentcatalog/review-pr" and "index.docker.io/agentcatalog/review-pr:latest")
126+ // resolve to the same store key that remote.Pull uses.
127+ storeKey , err := remote .NormalizeReference (a .reference )
128+ if err != nil {
129+ return nil , fmt .Errorf ("normalizing OCI reference %s: %w" , a .reference , err )
130+ }
131+
132+ // For digest references, the content is immutable. If we already have
133+ // the artifact locally, serve it directly without any network call.
134+ if remote .IsDigestReference (a .reference ) {
135+ if data , loadErr := loadArtifact (store , storeKey ); loadErr == nil {
136+ slog .Debug ("Serving digest-pinned OCI artifact from cache" , "ref" , a .reference )
137+ return data , nil
128138 }
129- return []byte (af ), nil
130139 }
131140
132- // Check if we have any local metadata (same as before)
133- _ , metaErr := store .GetArtifactMetadata (a .reference )
134- hasLocal := metaErr == nil
141+ // Check whether we have a local copy to fall back on.
142+ hasLocal := hasLocalArtifact (store , storeKey )
135143
136- // Always try normal pull first (preserves pull-interval behavior)
144+ // Pull from registry (checks remote digest, skips download if unchanged).
137145 if _ , pullErr := remote .Pull (ctx , a .reference , false ); pullErr != nil {
138146 if ! hasLocal {
139147 return nil , fmt .Errorf ("failed to pull OCI image %s: %w" , a .reference , pullErr )
140148 }
141-
142- slog .Debug (
143- "Failed to check for OCI reference updates, using cached version" ,
144- "ref" , a .reference ,
145- "error" , pullErr ,
146- )
149+ slog .Debug ("Failed to check for OCI reference updates, using cached version" ,
150+ "ref" , a .reference , "error" , pullErr )
147151 }
148152
149- // Try loading from store
150- data , err := tryLoad ( )
153+ // Try loading from store.
154+ data , err := loadArtifact ( store , storeKey )
151155 if err == nil {
152156 return data , nil
153157 }
154158
155- // If loading failed due to corruption, force re-pull
156- if errors .Is (err , content .ErrStoreCorrupted ) {
157- slog .Warn (
158- "Local OCI store corrupted, forcing re-pull" ,
159- "ref" , a .reference ,
160- )
159+ // If corrupted, force re-pull and try once more.
160+ if ! errors .Is (err , content .ErrStoreCorrupted ) {
161+ return nil , fmt .Errorf ("failed to load agent from OCI source %s: %w" , a .reference , err )
162+ }
161163
162- if _ , pullErr := remote .Pull (ctx , a .reference , true ); pullErr != nil {
163- return nil , fmt .Errorf ("failed to force re-pull OCI image %s: %w" , a .reference , pullErr )
164- }
164+ slog .Warn ("Local OCI store corrupted, forcing re-pull" , "ref" , a .reference )
165+ if _ , pullErr := remote .Pull (ctx , a .reference , true ); pullErr != nil {
166+ return nil , fmt .Errorf ("failed to force re-pull OCI image %s: %w" , a .reference , pullErr )
167+ }
165168
166- data , err = tryLoad ()
167- if err == nil {
168- return data , nil
169- }
169+ data , err = loadArtifact (store , storeKey )
170+ if err != nil {
171+ return nil , fmt .Errorf ("failed to load agent from OCI source %s: %w" , a .reference , err )
172+ }
173+ return data , nil
174+ }
175+
176+ // loadArtifact reads the agent YAML from the content store.
177+ func loadArtifact (store * content.Store , storeKey string ) ([]byte , error ) {
178+ af , err := store .GetArtifact (storeKey )
179+ if err != nil {
180+ return nil , err
170181 }
182+ return []byte (af ), nil
183+ }
171184
172- return nil , fmt .Errorf (
173- "failed to load agent from OCI source %s: %w" ,
174- a .reference ,
175- err ,
176- )
185+ // hasLocalArtifact reports whether the content store has metadata for the given key.
186+ func hasLocalArtifact (store * content.Store , storeKey string ) bool {
187+ _ , err := store .GetArtifactMetadata (storeKey )
188+ return err == nil
177189}
178190
179191// urlSource is used to load an agent configuration from an HTTP/HTTPS URL.
0 commit comments