| 138 | } |
| 139 | |
| 140 | func serveTaskPluginProtocol( |
| 141 | c *gin.Context, |
| 142 | pinned pluginruntime.PinnedEndpoint, |
| 143 | deps pluginProtocolBridgeDeps, |
| 144 | ) { |
| 145 | deps = deps.withDefaults() |
| 146 | generation := uint64(0) |
| 147 | if pinned.Generation != nil { |
| 148 | generation = pinned.Generation.Number |
| 149 | } |
| 150 | pluginKey := "" |
| 151 | if pinned.Plugin != nil { |
| 152 | pluginKey = pinned.Plugin.Meta.Key |
| 153 | } |
| 154 | logger.LogDebug( |
| 155 | c, |
| 156 | "task_plugin subsystem=protocol event=bridge_start generation=%d plugin=%q protocol=%q model=%q", |
| 157 | generation, |
| 158 | pluginKey, |
| 159 | pinned.Protocol, |
| 160 | c.GetString("resolved_task_model"), |
| 161 | ) |
| 162 | if !pluginruntime.SupportsHostProtocol(pinned.Protocol) { |
| 163 | logger.LogDebug(c, "task_plugin subsystem=protocol event=bridge_rejected generation=%d plugin=%q reason=unsupported_protocol", generation, pluginKey) |
| 164 | respondPluginProtocolError(c, http.StatusNotImplemented, "task_protocol_not_available", "Task protocol bridge is not available") |
| 165 | return |
| 166 | } |
| 167 | requestValue, exists := c.Get(pluginruntime.ContextKeyProtocolRequest) |
| 168 | protocolRequest, ok := requestValue.(pluginruntime.ProtocolRequestContext) |
| 169 | if !exists || !ok || protocolRequest.Protocol != pinned.Protocol { |
| 170 | logger.LogDebug(c, "task_plugin subsystem=protocol event=bridge_rejected generation=%d plugin=%q reason=invalid_protocol_context", generation, pluginKey) |
| 171 | respondPluginProtocolError(c, http.StatusInternalServerError, "task_protocol_error", "Task protocol request failed") |
| 172 | return |
| 173 | } |
| 174 | if definition, known := pluginruntime.HostProtocol(pinned.Protocol); known && len(definition.DefinedModes()) > 0 && pinned.Plugin != nil { |
| 175 | background := false |
| 176 | if body, ok := protocolRequest.Body.(map[string]any); ok && body["kind"] == string(pluginruntime.BodyJSON) { |
| 177 | if requestBody, ok := body["value"].(map[string]any); ok { |
| 178 | background, _ = requestBody["background"].(bool) |
| 179 | } |
| 180 | } |
| 181 | missing := false |
| 182 | if protocolRequest.Stream && !pinned.Plugin.Meta.ProtocolSupports(pinned.Protocol, "stream") { |
| 183 | missing = true |
| 184 | } |
| 185 | if background && !pinned.Plugin.Meta.ProtocolSupports(pinned.Protocol, "background") { |
| 186 | missing = true |
| 187 | } |
| 188 | if !protocolRequest.Stream && !background && !pinned.Plugin.Meta.ProtocolSupports(pinned.Protocol, "sync") { |
| 189 | missing = true |
| 190 | } |
| 191 | if missing { |
| 192 | logger.LogError(c, "pinned task plugin does not support the requested protocol form") |
| 193 | respondPluginProtocolError(c, http.StatusInternalServerError, "task_protocol_error", "Task protocol request failed") |
| 194 | return |
| 195 | } |
| 196 | } |
| 197 | logger.LogDebug( |