@@ -176,76 +176,86 @@ export namespace Plugin {
176176 Service ,
177177 Effect . gen ( function * ( ) {
178178 const bus = yield * Bus . Service
179+ const config = yield * Config . Service
179180
180181 const cache = yield * InstanceState . make < State > (
181182 Effect . fn ( "Plugin.state" ) ( function * ( ctx ) {
182183 const hooks : Hooks [ ] = [ ]
183184
184- yield * Effect . promise ( async ( ) => {
185- const { Server } = await import ( "../server/server" )
186-
187- const client = createOpencodeClient ( {
188- baseUrl : "http://localhost:4096" ,
189- directory : ctx . directory ,
190- headers : Flag . OPENCODE_SERVER_PASSWORD
191- ? {
192- Authorization : `Basic ${ Buffer . from ( `${ Flag . OPENCODE_SERVER_USERNAME ?? "opencode" } :${ Flag . OPENCODE_SERVER_PASSWORD } ` ) . toString ( "base64" ) } ` ,
193- }
194- : undefined ,
195- fetch : async ( ...args ) => Server . Default ( ) . fetch ( ...args ) ,
196- } )
197- const cfg = await Config . get ( )
198- const input : PluginInput = {
199- client,
200- project : ctx . project ,
201- worktree : ctx . worktree ,
202- directory : ctx . directory ,
203- get serverUrl ( ) : URL {
204- return Server . url ?? new URL ( "http://localhost:4096" )
205- } ,
206- $ : Bun . $ ,
207- }
185+ const { Server } = yield * Effect . promise ( ( ) => import ( "../server/server" ) )
186+
187+ const client = createOpencodeClient ( {
188+ baseUrl : "http://localhost:4096" ,
189+ directory : ctx . directory ,
190+ headers : Flag . OPENCODE_SERVER_PASSWORD
191+ ? {
192+ Authorization : `Basic ${ Buffer . from ( `${ Flag . OPENCODE_SERVER_USERNAME ?? "opencode" } :${ Flag . OPENCODE_SERVER_PASSWORD } ` ) . toString ( "base64" ) } ` ,
193+ }
194+ : undefined ,
195+ fetch : async ( ...args ) => Server . Default ( ) . fetch ( ...args ) ,
196+ } )
197+ const cfg = yield * config . get ( )
198+ const input : PluginInput = {
199+ client,
200+ project : ctx . project ,
201+ worktree : ctx . worktree ,
202+ directory : ctx . directory ,
203+ get serverUrl ( ) : URL {
204+ return Server . url ?? new URL ( "http://localhost:4096" )
205+ } ,
206+ $ : Bun . $ ,
207+ }
208208
209- for ( const plugin of INTERNAL_PLUGINS ) {
210- log . info ( "loading internal plugin" , { name : plugin . name } )
211- const init = await plugin ( input ) . catch ( ( err ) => {
209+ for ( const plugin of INTERNAL_PLUGINS ) {
210+ log . info ( "loading internal plugin" , { name : plugin . name } )
211+ const init = yield * Effect . tryPromise ( {
212+ try : ( ) => plugin ( input ) ,
213+ catch : ( err ) => {
212214 log . error ( "failed to load internal plugin" , { name : plugin . name , error : err } )
213- } )
214- if ( init ) hooks . push ( init )
215- }
216-
217- const plugins = Flag . OPENCODE_PURE ? [ ] : ( cfg . plugin ?? [ ] )
218- if ( Flag . OPENCODE_PURE && cfg . plugin ?. length ) {
219- log . info ( "skipping external plugins in pure mode" , { count : cfg . plugin . length } )
220- }
221- if ( plugins . length ) await Config . waitForDependencies ( )
222-
223- const loaded = await Promise . all ( plugins . map ( ( item ) => prepPlugin ( item ) ) )
224- for ( const load of loaded ) {
225- if ( ! load ) continue
226-
227- // Keep plugin execution sequential so hook registration and execution
228- // order remains deterministic across plugin runs.
229- await applyPlugin ( load , input , hooks ) . catch ( ( err ) => {
215+ } ,
216+ } ) . pipe ( Effect . option )
217+ if ( init . _tag === "Some" ) hooks . push ( init . value )
218+ }
219+
220+ const plugins = Flag . OPENCODE_PURE ? [ ] : ( cfg . plugin ?? [ ] )
221+ if ( Flag . OPENCODE_PURE && cfg . plugin ?. length ) {
222+ log . info ( "skipping external plugins in pure mode" , { count : cfg . plugin . length } )
223+ }
224+ if ( plugins . length ) yield * config . waitForDependencies ( )
225+
226+ const loaded = yield * Effect . promise ( ( ) => Promise . all ( plugins . map ( ( item ) => prepPlugin ( item ) ) ) )
227+ for ( const load of loaded ) {
228+ if ( ! load ) continue
229+
230+ // Keep plugin execution sequential so hook registration and execution
231+ // order remains deterministic across plugin runs.
232+ yield * Effect . tryPromise ( {
233+ try : ( ) => applyPlugin ( load , input , hooks ) ,
234+ catch : ( err ) => {
230235 const message = errorMessage ( err )
231236 log . error ( "failed to load plugin" , { path : load . spec , error : message } )
232- Bus . publish ( Session . Event . Error , {
237+ return message
238+ } ,
239+ } ) . pipe (
240+ Effect . catch ( ( message ) =>
241+ bus . publish ( Session . Event . Error , {
233242 error : new NamedError . Unknown ( {
234243 message : `Failed to load plugin ${ load . spec } : ${ message } ` ,
235244 } ) . toObject ( ) ,
236- } )
237- } )
238- }
239-
240- // Notify plugins of current config
241- for ( const hook of hooks ) {
242- try {
243- await ( hook as any ) . config ?.( cfg )
244- } catch ( err ) {
245+ } ) ,
246+ ) ,
247+ )
248+ }
249+
250+ // Notify plugins of current config
251+ for ( const hook of hooks ) {
252+ yield * Effect . tryPromise ( {
253+ try : ( ) => Promise . resolve ( ( hook as any ) . config ?.( cfg ) ) ,
254+ catch : ( err ) => {
245255 log . error ( "plugin config hook failed" , { error : err } )
246- }
247- }
248- } )
256+ } ,
257+ } ) . pipe ( Effect . ignore )
258+ }
249259
250260 // Subscribe to bus events, fiber interrupted when scope closes
251261 yield * bus . subscribeAll ( ) . pipe (
@@ -270,13 +280,11 @@ export namespace Plugin {
270280 > ( name : Name , input : Input , output : Output ) {
271281 if ( ! name ) return output
272282 const state = yield * InstanceState . get ( cache )
273- yield * Effect . promise ( async ( ) => {
274- for ( const hook of state . hooks ) {
275- const fn = hook [ name ] as any
276- if ( ! fn ) continue
277- await fn ( input , output )
278- }
279- } )
283+ for ( const hook of state . hooks ) {
284+ const fn = hook [ name ] as any
285+ if ( ! fn ) continue
286+ yield * Effect . promise ( ( ) => fn ( input , output ) )
287+ }
280288 return output
281289 } )
282290
@@ -293,7 +301,7 @@ export namespace Plugin {
293301 } ) ,
294302 )
295303
296- export const defaultLayer = layer . pipe ( Layer . provide ( Bus . layer ) )
304+ export const defaultLayer = layer . pipe ( Layer . provide ( Bus . layer ) , Layer . provide ( Config . defaultLayer ) )
297305 const { runPromise } = makeRuntime ( Service , defaultLayer )
298306
299307 export async function trigger <
0 commit comments