MCPcopy Index your code
hub / github.com/anomalyco/opencode / attempt

Function attempt

packages/opencode/src/plugin/loader.ts:149–192  ·  view source on GitHub ↗
(
    candidate: Candidate,
    kind: PluginKind,
    retry: boolean,
    finish: ((load: Loaded, origin: ConfigPlugin.Origin, retry: boolean) => Promise<R | undefined>) | undefined,
    missing: ((value: Missing, origin: ConfigPlugin.Origin, retry: boolean) => Promise<R | undefined>) | undefined,
    report: Report | undefined,
  )

Source from the content-addressed store, hash-verified

147 // Run one candidate through the full pipeline: resolve, optionally surface a missing entry,
148 // import the module, and finally let the caller transform the loaded plugin into any result type.
149 async function attempt<R>(
150 candidate: Candidate,
151 kind: PluginKind,
152 retry: boolean,
153 finish: ((load: Loaded, origin: ConfigPlugin.Origin, retry: boolean) => Promise<R | undefined>) | undefined,
154 missing: ((value: Missing, origin: ConfigPlugin.Origin, retry: boolean) => Promise<R | undefined>) | undefined,
155 report: Report | undefined,
156 ): Promise<AttemptResult<R>> {
157 const plan = candidate.plan
158 const filePlugin = pluginSource(plan.spec) === "file"
159
160 // Deprecated plugin packages are silently ignored because they are now built in.
161 if (plan.deprecated) return { retry: false }
162
163 report?.start?.(candidate, retry)
164
165 const resolved = await resolve(plan, kind)
166 if (!resolved.ok) {
167 if (resolved.stage === "missing") {
168 // Missing entrypoints are handled separately so callers can still inspect package metadata,
169 // for example to load theme files from a tui plugin package that has no code entrypoint.
170 if (missing) {
171 const value = await missing(resolved.value, candidate.origin, retry)
172 if (value !== undefined) return { value, retry: false }
173 }
174 report?.missing?.(candidate, retry, resolved.value.message, resolved.value)
175 return { retry: false }
176 }
177 report?.error?.(candidate, retry, resolved.stage, resolved.error)
178 return { retry: filePlugin && isRetryableResolveError(resolved.stage, resolved.error) }
179 }
180
181 const loaded = await load(resolved.value)
182 if (!loaded.ok) {
183 report?.error?.(candidate, retry, "load", loaded.error, resolved.value)
184 return { retry: false }
185 }
186
187 // The default behavior is to return the successfully loaded plugin as-is, but callers can
188 // provide a finisher to adapt the result into a more specific runtime shape.
189 if (!finish) return { value: loaded.value as R, retry: false }
190 const value = await finish(loaded.value, candidate.origin, retry)
191 return { value, retry: false }
192 }
193
194 type Input<R> = {
195 items: ConfigPlugin.Origin[]

Callers 1

loadExternalFunction · 0.70

Calls 7

pluginSourceFunction · 0.90
isRetryableResolveErrorFunction · 0.85
resolveFunction · 0.70
missingFunction · 0.70
loadFunction · 0.70
finishFunction · 0.50
startMethod · 0.45

Tested by

no test coverage detected