Load all plugins from the given spec list. Each spec is either: - `file:///path/to/plugin.ts` — loaded directly - An npm package name (e.g. `opencode-anthropic-auth@0.0.13`)
(
&self,
specs: &[String],
context: &PluginContext,
)
| 81 | /// - `file:///path/to/plugin.ts` — loaded directly |
| 82 | /// - An npm package name (e.g. `opencode-anthropic-auth@0.0.13`) |
| 83 | pub async fn load_all( |
| 84 | &self, |
| 85 | specs: &[String], |
| 86 | context: &PluginContext, |
| 87 | ) -> Result<(), PluginLoaderError> { |
| 88 | // Collect npm packages that need installing |
| 89 | let npm_specs: Vec<&str> = specs |
| 90 | .iter() |
| 91 | .filter(|s| !s.starts_with("file://")) |
| 92 | .map(|s| s.as_str()) |
| 93 | .collect(); |
| 94 | |
| 95 | if !npm_specs.is_empty() { |
| 96 | self.install_npm_packages(&npm_specs).await?; |
| 97 | } |
| 98 | |
| 99 | // Spawn each plugin |
| 100 | for spec in specs { |
| 101 | let plugin_path = self.resolve_plugin(spec)?; |
| 102 | // For npm packages (non file:// specs), set cwd to the npm dir |
| 103 | // so bare-specifier imports resolve against node_modules/. |
| 104 | let cwd = if !spec.starts_with("file://") { |
| 105 | Some(self.npm_dir()) |
| 106 | } else { |
| 107 | None |
| 108 | }; |
| 109 | match PluginSubprocess::spawn( |
| 110 | self.runtime, |
| 111 | self.host_script_path.to_str().unwrap_or("plugin-host.ts"), |
| 112 | &plugin_path, |
| 113 | context.clone(), |
| 114 | cwd.as_deref(), |
| 115 | ) |
| 116 | .await |
| 117 | { |
| 118 | Ok(client) => { |
| 119 | tracing::info!( |
| 120 | plugin = client.name(), |
| 121 | hooks = ?client.hooks(), |
| 122 | has_auth = client.auth_meta().is_some(), |
| 123 | "loaded TS plugin" |
| 124 | ); |
| 125 | let client = Arc::new(client); |
| 126 | |
| 127 | // If the plugin provides auth, create an auth bridge |
| 128 | if let Some(auth_meta) = client.auth_meta().cloned() { |
| 129 | let provider = auth_meta.provider.clone(); |
| 130 | let bridge = |
| 131 | Arc::new(PluginAuthBridge::new(Arc::clone(&client), auth_meta)); |
| 132 | tracing::info!( |
| 133 | plugin = client.name(), |
| 134 | provider = provider.as_str(), |
| 135 | methods = ?bridge.methods(), |
| 136 | "registered plugin auth bridge" |
| 137 | ); |
| 138 | let mut bridges = self.auth_bridges.write().await; |
| 139 | bridges.insert(provider, bridge); |
| 140 | } |
no test coverage detected