ronantakizawa/codereview-bench huggingface dataset:
Repository: benbusby/whoogle-search
File: app/static/js/currency.js (JavaScript)

Code before:
function Convert(n1, n2, conversion_factor) {
    // id's for currency input boxes
    id1 = "cb" + n1; 
    id2 = "cb" + n2;

    // getting the value of the input box that just got filled
    var input_box = document.getElementById(id1).value;

    // updating the other input box after conversion
    document.getElementById(id2).value = ((input_box * conversion_factor).toFixed(2));
}

Review comment (suggestion):
ES6/formatting updates:

```suggestion
const convert = (n1, n2, conversionFactor) => {
    // id's for currency input boxes
    let id1 = "cb" + n1; 
    let id2 = "cb" + n2;

    // getting the value of the input box that just got filled
    let inputBox = document.getElementById(id1).value;

    // updating the other input box after conversion
    document.getElementById(id2).value = ((inputBox * conversionFactor).toFixed(2));
}
```

Code after:
const convert = (n1, n2, conversionFactor) => {
    // id's for currency input boxes
    let id1 = "cb" + n1; 
    let id2 = "cb" + n2;
    // getting the value of the input box that just got filled
    let inputBox = document.getElementById(id1).value;
    // updating the other input box after conversion
    document.getElementById(id2).value = ((inputBox * conversionFactor).toFixed(2));
}
Repository: benbusby/whoogle-search
File: app/utils/results.py (Python)

Code before:
    # Creating a new div for the input boxes
    conversion_box = soup.new_tag('div')
    conversion_box['class'] = 'conversion_box'

    # Currency to be converted from
    input_box1 = soup.new_tag('input')
    input_box1['id'] = 'cb1'
    input_box1['type'] = 'number'
    input_box1['class'] = 'cb'
    input_box1['value'] = conversion_details['currencyValue1']
    input_box1['oninput'] = f'Convert(1, 2, {1 / conversion_factor})'

    label_box1 = soup.new_tag('label')
    label_box1['for'] = 'cb1'
    label_box1['class'] = 'cb_label'
    label_box1.append(conversion_details['currencyLabel1'])

    br = soup.new_tag('br')

    # Currency to be converted to
    input_box2 = soup.new_tag('input')
    input_box2['id'] = 'cb2'
    input_box2['type'] = 'number'
    input_box2['class'] = 'cb'
    input_box2['value'] = conversion_details['currencyValue2']
    input_box2['oninput'] = f'Convert(2, 1, {conversion_factor})'

    label_box2 = soup.new_tag('label')
    label_box2['for'] = 'cb2'
    label_box2['class'] = 'cb_label'
    label_box2.append(conversion_details['currencyLabel2'])

    conversion_box.append(input_box1)
    conversion_box.append(label_box1)
    conversion_box.append(br)
    conversion_box.append(input_box2)
    conversion_box.append(label_box2)

    element1.insert_before(conversion_box)
    return soup


Review comment (suggestion):
Same as above

```suggestion
    input_box2['oninput'] = f'convert(2, 1, {conversion_factor})'
```

Code after:
    # Creating a new div for the input boxes
    conversion_box = soup.new_tag('div')
    conversion_box['class'] = 'conversion_box'

    # Currency to be converted from
    input_box1 = soup.new_tag('input')
    input_box1['id'] = 'cb1'
    input_box1['type'] = 'number'
    input_box1['class'] = 'cb'
    input_box1['value'] = conversion_details['currencyValue1']
    input_box1['oninput'] = f'convert(1, 2, {1 / conversion_factor})'

    label_box1 = soup.new_tag('label')
    label_box1['for'] = 'cb1'
    label_box1['class'] = 'cb_label'
    label_box1.append(conversion_details['currencyLabel1'])

    br = soup.new_tag('br')

    # Currency to be converted to
    input_box2 = soup.new_tag('input')
    input_box2['id'] = 'cb2'
    input_box2['type'] = 'number'
    input_box2['class'] = 'cb'
    input_box2['value'] = conversion_details['currencyValue2']
    input_box2['oninput'] = f'convert(2, 1, {conversion_factor})'

    label_box2 = soup.new_tag('label')
    label_box2['for'] = 'cb2'
    label_box2['class'] = 'cb_label'
    label_box2.append(conversion_details['currencyLabel2'])

    conversion_box.append(input_box1)
    conversion_box.append(label_box1)
    conversion_box.append(br)
    conversion_box.append(input_box2)
    conversion_box.append(label_box2)

    element1.insert_before(conversion_box)
    return soup
Repository: bilibili/kratos
File: contrib/registry/consul/client.go (Go)

Code before:
	MultiDatacenter  Datacenter = "MULTI"
)

// Client is consul client config
type Client struct {
	dc     Datacenter
	cli    *api.Client
	ctx    context.Context
	cancel context.CancelFunc

	// resolve service entry endpoints
	resolver ServiceResolver
	// healthcheck time interval in seconds
	healthcheckInterval int
	// heartbeat enable heartbeat
	heartbeat bool
	// deregisterCriticalServiceAfter time interval in seconds
	deregisterCriticalServiceAfter int
	// serviceChecks  user custom checks
	serviceChecks api.AgentServiceChecks
}

type ClientOption func(c *Client)

// WithDataCenter datacenter names.
func WithDataCenter(dc Datacenter) ClientOption {
	return func(c *Client) {
		c.dc = dc
	}
}

// NewClient creates consul client
func NewClient(cli *api.Client, opts ...ClientOption) *Client {
	c := &Client{
		cli:                            cli,
		resolver:                       defaultResolver,
		healthcheckInterval:            10,
		heartbeat:                      true,
		deregisterCriticalServiceAfter: 600,
	}
	for _, opt := range opts {
		opt(c)
	}

	c.ctx, c.cancel = context.WithCancel(context.Background())
	return c
}

func defaultResolver(_ context.Context, entries []*api.ServiceEntry) []*registry.ServiceInstance {
	services := make([]*registry.ServiceInstance, 0, len(entries))
	for _, entry := range entries {

Review comment (suggestion):
`WithDatacenter` would it be better
```
dcs, err := c.cli.Catalog().Datacenters()
```

Code after:
	MultiDatacenter  Datacenter = "MULTI"
)

// Client is consul client config
type Client struct {
	dc     Datacenter
	cli    *api.Client
	ctx    context.Context
	cancel context.CancelFunc

	// resolve service entry endpoints
	resolver ServiceResolver
	// healthcheck time interval in seconds
	healthcheckInterval int
	// heartbeat enable heartbeat
	heartbeat bool
	// deregisterCriticalServiceAfter time interval in seconds
	deregisterCriticalServiceAfter int
	// serviceChecks  user custom checks
	serviceChecks api.AgentServiceChecks
}

// Deprecated use newClient instead.
func NewClient(cli *api.Client) *Client {
	return newClient(cli, SingleDatacenter)
}

func newClient(cli *api.Client, dc Datacenter) *Client {
	c := &Client{
		dc:                             dc,
		cli:                            cli,
		resolver:                       defaultResolver,
		healthcheckInterval:            10,
		heartbeat:                      true,
		deregisterCriticalServiceAfter: 600,
	}

	c.ctx, c.cancel = context.WithCancel(context.Background())
	return c
}

func defaultResolver(_ context.Context, entries []*api.ServiceEntry) []*registry.ServiceInstance {
	services := make([]*registry.ServiceInstance, 0, len(entries))
	for _, entry := range entries {
		var version string
		for _, tag := range entry.Service.Tags {
			ss := strings.SplitN(tag, "=", 2)
			if len(ss) == 2 && ss[0] == "version" {
				version = ss[1]
			}
		}
Repository: bilibili/kratos
File: contrib/registry/consul/registry.go (Go)

Code before:
			serviceName: name,
		}
		r.registry[name] = set
	}

	// init watcher
	w := &watcher{
		event: make(chan struct{}, 1),
	}
	w.ctx, w.cancel = context.WithCancel(ctx)
	w.set = set
	set.lock.Lock()
	set.watcher[w] = struct{}{}
	set.lock.Unlock()
	ss, _ := set.services.Load().([]*registry.ServiceInstance)
	if len(ss) > 0 {
		// If the service has a value, it needs to be pushed to the watcher,
		// otherwise the initial data may be blocked forever during the watch.
		w.event <- struct{}{}
	}

	err := r.resolve(ctx, set)
	if err != nil {
		return nil, err
	}

	return w, nil
}

func (r *Registry) resolve(ctx context.Context, ss *serviceSet) error {
	timeoutCtx, cancel := context.WithTimeout(ctx, r.timeout)
	defer cancel()

	services, idx, err := r.cli.Service(timeoutCtx, ss.serviceName, 0, true)
	if err != nil {
		return err
	}
	if len(services) > 0 {
		ss.broadcast(services)
	}

	go func() {
		ticker := time.NewTicker(time.Second)
		defer ticker.Stop()
		for {
			select {
			case <-ticker.C:
				timeoutCtx, cancel := context.WithTimeout(context.Background(), r.timeout)
				tmpService, tmpIdx, err := r.cli.Service(timeoutCtx, ss.serviceName, idx, true)
				cancel()
				if err != nil {

Review comment (suggestion):
```go
if err := r.resolve(ctx, set); err != nil {
     return nil, err
}
```

Code after:
			serviceName: name,
		}
		set.ctx, set.cancel = context.WithCancel(context.Background())
		r.registry[name] = set
	}

	// init watcher
	w := &watcher{
		event: make(chan struct{}, 1),
	}
	w.ctx, w.cancel = context.WithCancel(ctx)
	w.set = set
	set.lock.Lock()
	set.watcher[w] = struct{}{}
	set.lock.Unlock()
	ss, _ := set.services.Load().([]*registry.ServiceInstance)
	if len(ss) > 0 {
		// If the service has a value, it needs to be pushed to the watcher,
		// otherwise the initial data may be blocked forever during the watch.
		w.event <- struct{}{}
	}
	if !ok {
		if err := r.resolve(set.ctx, set); err != nil {
			return nil, err
		}
	}
	return w, nil
}

func (r *Registry) resolve(ctx context.Context, ss *serviceSet) error {
	timeoutCtx, cancel := context.WithTimeout(ctx, r.timeout)
	defer cancel()

	services, idx, err := r.cli.Service(timeoutCtx, ss.serviceName, 0, true)
	if err != nil {
		return err
	}
	if len(services) > 0 {
		ss.broadcast(services)
	}

	go func() {
		ticker := time.NewTicker(time.Second)
		defer ticker.Stop()
		for {
			select {
			case <-ticker.C:
				timeoutCtx, cancel := context.WithTimeout(context.Background(), r.timeout)
				tmpService, tmpIdx, err := r.cli.Service(timeoutCtx, ss.serviceName, idx, true)
				cancel()
				if err != nil {
Repository: bilibili/kratos
File: transport/grpc/server.go (Go)

Code before:
	}
}

// Listener with server lis
func Listener(lis net.Listener) ServerOption {
	return func(s *Server) {
		s.lis = lis
	}
}

// UnaryInterceptor returns a ServerOption that sets the UnaryServerInterceptor for the server.
func UnaryInterceptor(in ...grpc.UnaryServerInterceptor) ServerOption {
	return func(s *Server) {
		s.unaryInts = in
	}
}

// StreamInterceptor returns a ServerOption that sets the StreamServerInterceptor for the server.
func StreamInterceptor(in ...grpc.StreamServerInterceptor) ServerOption {
	return func(s *Server) {
		s.streamInts = in
	}
}

// DisuseReflection disuse reflection.
func DisuseReflection(enable bool) ServerOption {
	return func(s *Server) {
		s.disuseReflection = enable
	}
}

// Options with grpc options.
func Options(opts ...grpc.ServerOption) ServerOption {
	return func(s *Server) {
		s.grpcOpts = opts
	}
}

// Server is a gRPC server wrapper.
type Server struct {
	*grpc.Server
	baseCtx          context.Context
	tlsConf          *tls.Config
	lis              net.Listener
	err              error
	network          string
	address          string
	endpoint         *url.URL
	timeout          time.Duration
	middleware       matcher.Matcher
	streamMiddleware matcher.Matcher

Review comment (suggestion):
Why do we still need to pass the `enable` parameter when the method is called `Disuse` Also, usually `disable` is used

Code after:
	}
}

// Listener with server lis
func Listener(lis net.Listener) ServerOption {
	return func(s *Server) {
		s.lis = lis
	}
}

// UnaryInterceptor returns a ServerOption that sets the UnaryServerInterceptor for the server.
func UnaryInterceptor(in ...grpc.UnaryServerInterceptor) ServerOption {
	return func(s *Server) {
		s.unaryInts = in
	}
}

// StreamInterceptor returns a ServerOption that sets the StreamServerInterceptor for the server.
func StreamInterceptor(in ...grpc.StreamServerInterceptor) ServerOption {
	return func(s *Server) {
		s.streamInts = in
	}
}

// DisableReflection disable grpc reflection.
func DisableReflection() ServerOption {
	return func(s *Server) {
		s.disableReflection = true
	}
}

// Options with grpc options.
func Options(opts ...grpc.ServerOption) ServerOption {
	return func(s *Server) {
		s.grpcOpts = opts
	}
}

// Server is a gRPC server wrapper.
type Server struct {
	*grpc.Server
	baseCtx           context.Context
	tlsConf           *tls.Config
	lis               net.Listener
	err               error
	network           string
	address           string
	endpoint          *url.URL
	timeout           time.Duration
	middleware        matcher.Matcher
	streamMiddleware  matcher.Matcher
Repository: block/goose
File: crates/goose-cli/src/session/output.rs (Rust)

Code before:
        .set_param("GOOSE_CLI_THEME", theme.as_config_string())
        .expect("Failed to set theme");
    CURRENT_THEME.with(|t| *t.borrow_mut() = theme);

    let config = Config::global();
    let theme_str = match theme {
        Theme::Light => "light",
        Theme::Dark => "dark",
        Theme::Ansi => "ansi",
    };

    if let Err(e) = config.set_param("GOOSE_CLI_THEME", theme_str) {
        eprintln!("Failed to save theme setting to config: {}", e);
    }
}

pub fn get_theme() -> Theme {
    CURRENT_THEME.with(|t| *t.borrow())
}

pub fn toggle_full_tool_output() -> bool {
    SHOW_FULL_TOOL_OUTPUT.with(|s| {
        let new_value = !*s.borrow();
        *s.borrow_mut() = new_value;
        new_value
    })
}

pub fn get_show_full_tool_output() -> bool {
    SHOW_FULL_TOOL_OUTPUT.with(|s| *s.borrow())
}

// Simple wrapper around spinner to manage its state
#[derive(Default)]
pub struct ThinkingIndicator {
    spinner: Option<cliclack::ProgressBar>,
}

impl ThinkingIndicator {
    pub fn show(&mut self) {
        let spinner = cliclack::spinner();
        if Config::global()
            .get_param("RANDOM_THINKING_MESSAGES")
            .unwrap_or(true)
        {
            spinner.start(format!(
                "{}...",
                super::thinking::get_random_thinking_message()
            ));
        } else {
            spinner.start("Thinking...");

Review comment (suggestion):
you can use borrow_mut for one go:

```
pub fn toggle_full_tool_output() -> bool {
    SHOW_FULL_TOOL_OUTPUT.with(|s| {
        let mut val = s.borrow_mut();
        *val = !*val;
        *val
    })
}
```

Code after:
        .set_param("GOOSE_CLI_THEME", theme.as_config_string())
        .expect("Failed to set theme");
    CURRENT_THEME.with(|t| *t.borrow_mut() = theme);

    let config = Config::global();
    let theme_str = match theme {
        Theme::Light => "light",
        Theme::Dark => "dark",
        Theme::Ansi => "ansi",
    };

    if let Err(e) = config.set_param("GOOSE_CLI_THEME", theme_str) {
        eprintln!("Failed to save theme setting to config: {}", e);
    }
}

pub fn get_theme() -> Theme {
    CURRENT_THEME.with(|t| *t.borrow())
}

pub fn toggle_full_tool_output() -> bool {
    SHOW_FULL_TOOL_OUTPUT.with(|s| {
        let mut val = s.borrow_mut();
        *val = !*val;
        *val
    })
}

pub fn get_show_full_tool_output() -> bool {
    SHOW_FULL_TOOL_OUTPUT.with(|s| *s.borrow())
}

// Simple wrapper around spinner to manage its state
#[derive(Default)]
pub struct ThinkingIndicator {
    spinner: Option<cliclack::ProgressBar>,
}

impl ThinkingIndicator {
    pub fn show(&mut self) {
        let spinner = cliclack::spinner();
        if Config::global()
            .get_param("RANDOM_THINKING_MESSAGES")
            .unwrap_or(true)
        {
            spinner.start(format!(
                "{}...",
                super::thinking::get_random_thinking_message()
            ));
        } else {
            spinner.start("Thinking...");
Repository: block/goose
File: ui/desktop/src/components/McpApps/McpAppRenderer.tsx (TypeScript)

Code before:
        <div className="text-red-700 dark:text-red-300">Failed to load MCP app: {error}</div>
      </div>
    );
  }

  if (!resourceHtml) {
    return (
      <div className="mt-3 p-4 border border-borderSubtle rounded-lg bg-bgApp">
        <div className="flex items-center justify-center" style={{ minHeight: '200px' }}>
          Loading MCP app...
        </div>
      </div>
    );
  }

  return (
    <div className={cn('mt-3 bg-bgApp', 'border border-borderSubtle rounded-lg overflow-hidden')}>
      {proxyUrl ? (
        <iframe
          ref={iframeRef}
          src={proxyUrl}
          style={{
            width: '100%',
            height: `${iframeHeight}px`,
            border: 'none',
            overflow: 'hidden',
          }}
          sandbox="allow-scripts allow-same-origin"
        />
      ) : (
        <div
          style={{
            width: '100%',
            minHeight: '200px',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
          }}
        >
          Loading...
        </div>
      )}
    </div>
  );
}


Review comment (refactor):
@DOsinga PTAL

I unified `resource.html` and `proxyUrl` as we don't need a discrete state for `proxyUrl` loading 

Also, leaving this inline instead of extracting as a const. I noticed a hard-to-reproduce issue where the iframe ref _might_ have gotten lost or something... the rendered mcp app would be sitting there w/ no messages being sent down. Maybe a closure issue? Not sure. But I think what I got works. 

Code after:
    resourceCsp: resource.csp,
    resourceUri,
    toolInput,
    toolInputPartial,
    toolResult,
    toolCancelled,
    onMcpRequest: handleMcpRequest,
    onSizeChanged: handleSizeChanged,
  });

  if (error) {
    return (
      <div className="p-4 border border-red-500 rounded-lg bg-red-50 dark:bg-red-900/20">
        <div className="text-red-700 dark:text-red-300">Failed to load MCP app: {error}</div>
      </div>
    );
  }

  return (
    <div
      className={cn(
        'bg-bgApp overflow-hidden',
        resource.prefersBorder ? 'border border-borderSubtle rounded-lg' : 'my-6'
      )}
    >
      {resource.html && proxyUrl ? (
        <iframe
          ref={iframeRef}
          src={proxyUrl}
          style={{
            width: '100%',
            height: `${iframeHeight}px`,
            border: 'none',
            overflow: 'hidden',
          }}
          sandbox="allow-scripts allow-same-origin"
        />
      ) : (
        <div className="flex items-center justify-center p-4" style={{ minHeight: '200px' }}>
          Loading MCP app...
        </div>
      )}
    </div>
  );
}
Repository: block/goose
File: crates/goose/src/agents/subagent_task_config.rs (Rust)

Code before:
}

impl TaskConfig {
    pub fn new(
        provider: Arc<dyn Provider>,
        parent_session_id: &str,
        parent_working_dir: &Path,
        extensions: Vec<ExtensionConfig>,
    ) -> Self {
        Self::with_max_turns(
            provider,
            parent_session_id,
            parent_working_dir,
            extensions,
            None,
        )
    }

    pub fn with_max_turns(
        provider: Arc<dyn Provider>,
        parent_session_id: &str,
        parent_working_dir: &Path,
        extensions: Vec<ExtensionConfig>,
        max_turns_override: Option<usize>,
    ) -> Self {
        let max_turns = max_turns_override.or_else(|| {
            env::var(GOOSE_SUBAGENT_MAX_TURNS_ENV_VAR)
                .ok()
                .and_then(|val| val.parse::<usize>().ok())
                .or(Some(DEFAULT_SUBAGENT_MAX_TURNS))
        });
        Self {
            provider,
            parent_session_id: parent_session_id.to_owned(),
            parent_working_dir: parent_working_dir.to_owned(),
            extensions,
            max_turns,
        }
    }
}

// Note: The actual TaskConfig behavior is tested in crates/goose/tests/agent.rs
// in the max_turns_tests module, which tests the full integration with real providers.
// Unit tests here would require mocking Provider, which adds complexity without value.


Review comment (suggestion):
we can leave this default case in the constructor as before.

with_max_turns can be something like:

```
  pub fn with_max_turns(mut self, max_turns: Option<usize>) -> Self {
      if let Some(turns) = max_turns {
          self.max_turns = Some(turns);
      }
      self
  }
```

Code after:
}

impl TaskConfig {
    pub fn new(
        provider: Arc<dyn Provider>,
        parent_session_id: &str,
        parent_working_dir: &Path,
        extensions: Vec<ExtensionConfig>,
    ) -> Self {
        Self {
            provider,
            parent_session_id: parent_session_id.to_owned(),
            parent_working_dir: parent_working_dir.to_owned(),
            extensions,
            max_turns: Some(
                env::var(GOOSE_SUBAGENT_MAX_TURNS_ENV_VAR)
                    .ok()
                    .and_then(|val| val.parse::<usize>().ok())
                    .unwrap_or(DEFAULT_SUBAGENT_MAX_TURNS),
            ),
        }
    }

    pub fn with_max_turns(mut self, max_turns: Option<usize>) -> Self {
        if let Some(turns) = max_turns {
            self.max_turns = Some(turns);
        }
        self
    }
}
Repository: block/goose
File: crates/goose-server/src/routes/session.rs (Rust)

Code before:
}

#[utoipa::path(
    get,
    path = "/sessions/search",
    params(
        ("query" = String, Query, description = "Search query string"),
        ("limit" = Option<usize>, Query, description = "Maximum results (default: 10, max: 50)"),
        ("after_date" = Option<String>, Query, description = "Filter after date (ISO 8601)"),
        ("before_date" = Option<String>, Query, description = "Filter before date (ISO 8601)")
    ),
    responses(
        (status = 200, description = "Search results", body = SearchSessionsResponse),
        (status = 400, description = "Bad request - Invalid query"),
        (status = 401, description = "Unauthorized"),
        (status = 500, description = "Internal server error")
    ),
    security(
        ("api_key" = [])
    ),
    tag = "Session Management"
)]
async fn search_sessions(
    State(state): State<Arc<AppState>>,
    axum::extract::Query(params): axum::extract::Query<SearchSessionsQuery>,
) -> Result<Json<SearchSessionsResponse>, StatusCode> {
    let query = params.query.trim();
    if query.is_empty() {
        return Err(StatusCode::BAD_REQUEST);
    }

    let limit = params.limit.min(50);

    let after_date = params
        .after_date
        .and_then(|s| chrono::DateTime::parse_from_rfc3339(&s).ok())
        .map(|dt| dt.with_timezone(&chrono::Utc));

    let before_date = params
        .before_date
        .and_then(|s| chrono::DateTime::parse_from_rfc3339(&s).ok())
        .map(|dt| dt.with_timezone(&chrono::Utc));

    let search_results = state
        .session_manager()
        .search_chat_history(query, Some(limit), after_date, before_date, None)
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    let results: Vec<SearchSessionResult> = search_results
        .results

Review comment (suggestion):
I wonder if it would make sense to return an actual Conversation object here with the truncated messages. it is all local so it should be fast enough and that way we don't create an extra type which is handy when we want to do other things with the returned session

Code after:
    let before_date = params
        .before_date
        .and_then(|s| chrono::DateTime::parse_from_rfc3339(&s).ok())
        .map(|dt| dt.with_timezone(&chrono::Utc));

    let search_results = state
        .session_manager()
        .search_chat_history(query, Some(limit), after_date, before_date, None)
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    // Get full Session objects for matching session IDs
    let session_ids: Vec<String> = search_results
        .results
        .into_iter()
        .map(|r| r.session_id)
        .collect();

    let all_sessions = state
        .session_manager()
        .list_sessions()
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    let matching_sessions: Vec<Session> = all_sessions
        .into_iter()
        .filter(|s| session_ids.contains(&s.id))
        .collect();

    Ok(Json(matching_sessions))
}