mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-06 14:22:47 +02:00
Skip middleware gate for native body-gated tools to restore approval-card context.
This commit is contained in:
parent
277bd50f37
commit
7735becd02
20 changed files with 72 additions and 27 deletions
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles deliverables tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles memory tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles research tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles airtable tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles calendar tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles clickup tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles confluence tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles discord tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles dropbox tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles gmail tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles google drive tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles jira tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles linear tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles luma tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles notion tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles onedrive tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles slack tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from app.agents.multi_agent_with_deepagents.subagents.shared.md_file_reader impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolsPermissions,
|
||||
merge_tools_permissions,
|
||||
middleware_gated_interrupt_on,
|
||||
)
|
||||
from app.agents.multi_agent_with_deepagents.subagents.shared.subagent_builder import (
|
||||
pack_subagent,
|
||||
|
|
@ -38,7 +39,7 @@ def build_subagent(
|
|||
for row in (*merged_tools_bucket["allow"], *merged_tools_bucket["ask"])
|
||||
if row.get("tool") is not None
|
||||
]
|
||||
interrupt_on = {r["name"]: True for r in merged_tools_bucket["ask"] if r.get("name")}
|
||||
interrupt_on = middleware_gated_interrupt_on(merged_tools_bucket)
|
||||
description = read_md_file(__package__, "description").strip()
|
||||
if not description:
|
||||
description = "Handles teams tasks for this workspace."
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ from app.agents.multi_agent_with_deepagents.subagents.mcp_tools.permissions impo
|
|||
from app.agents.multi_agent_with_deepagents.subagents.shared.permissions import (
|
||||
ToolPermissionItem,
|
||||
ToolsPermissions,
|
||||
tool_permission_row,
|
||||
mcp_tool_permission_row,
|
||||
)
|
||||
from app.agents.new_chat.tools.mcp_tool import load_mcp_tools
|
||||
from app.db import SearchSourceConnector
|
||||
|
|
@ -125,15 +125,15 @@ def _split_tools_by_permissions(
|
|||
for t in tools:
|
||||
meta: dict[str, Any] = getattr(t, "metadata", None) or {}
|
||||
if meta.get("hitl") is False:
|
||||
allow.append(tool_permission_row(t))
|
||||
allow.append(mcp_tool_permission_row(t))
|
||||
continue
|
||||
key = _get_mcp_tool_name(t)
|
||||
if key in allow_names:
|
||||
allow.append(tool_permission_row(t))
|
||||
allow.append(mcp_tool_permission_row(t))
|
||||
elif key in ask_names:
|
||||
ask.append(tool_permission_row(t))
|
||||
ask.append(mcp_tool_permission_row(t))
|
||||
else:
|
||||
ask.append(tool_permission_row(t))
|
||||
ask.append(mcp_tool_permission_row(t))
|
||||
return {"allow": allow, "ask": ask}
|
||||
|
||||
|
||||
|
|
@ -143,8 +143,14 @@ async def load_mcp_tools_by_connector(
|
|||
session: AsyncSession,
|
||||
search_space_id: int,
|
||||
) -> dict[str, ToolsPermissions]:
|
||||
"""Load MCP tools and split rows using ``TOOLS_PERMISSIONS_BY_AGENT`` name sets."""
|
||||
flat = await load_mcp_tools(session, search_space_id)
|
||||
"""Load MCP tools and split rows using ``TOOLS_PERMISSIONS_BY_AGENT`` name sets.
|
||||
|
||||
Pass ``bypass_internal_hitl=True`` so the subagent's
|
||||
``HumanInTheLoopMiddleware`` is the single HITL gate.
|
||||
"""
|
||||
flat = await load_mcp_tools(
|
||||
session, search_space_id, bypass_internal_hitl=True
|
||||
)
|
||||
id_map, name_map = await fetch_mcp_connector_metadata_maps(session, search_space_id)
|
||||
buckets = partition_mcp_tools_by_connector(flat, id_map, name_map)
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -2,16 +2,21 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import NotRequired, TypedDict
|
||||
from typing import Literal, NotRequired, TypedDict
|
||||
|
||||
from langchain_core.tools import BaseTool
|
||||
|
||||
# ``native`` rows self-gate via ``request_approval`` in the tool body;
|
||||
# ``mcp`` rows are gated by ``HumanInTheLoopMiddleware`` via ``interrupt_on``.
|
||||
ToolKind = Literal["native", "mcp"]
|
||||
|
||||
|
||||
class ToolPermissionItem(TypedDict):
|
||||
"""``name`` is always set; ``tool`` is present when a bound tool exists."""
|
||||
"""``name`` is always set; ``tool`` is present when a bound tool exists; ``kind`` defaults to ``native`` when absent."""
|
||||
|
||||
name: str
|
||||
tool: NotRequired[BaseTool]
|
||||
kind: NotRequired[ToolKind]
|
||||
|
||||
|
||||
class ToolsPermissions(TypedDict):
|
||||
|
|
@ -26,6 +31,11 @@ def tool_permission_row(tool: BaseTool) -> ToolPermissionItem:
|
|||
return {"name": getattr(tool, "name", "") or "", "tool": tool}
|
||||
|
||||
|
||||
def mcp_tool_permission_row(tool: BaseTool) -> ToolPermissionItem:
|
||||
"""Build one allow/ask row tagged ``kind="mcp"`` so it routes through ``HumanInTheLoopMiddleware``."""
|
||||
return {"name": getattr(tool, "name", "") or "", "tool": tool, "kind": "mcp"}
|
||||
|
||||
|
||||
def merge_tools_permissions(
|
||||
base: ToolsPermissions,
|
||||
extra: ToolsPermissions | None,
|
||||
|
|
@ -37,3 +47,14 @@ def merge_tools_permissions(
|
|||
"allow": [*base["allow"], *extra["allow"]],
|
||||
"ask": [*base["ask"], *extra["ask"]],
|
||||
}
|
||||
|
||||
|
||||
def middleware_gated_interrupt_on(
|
||||
bucket: ToolsPermissions,
|
||||
) -> dict[str, bool]:
|
||||
"""``interrupt_on`` for ``ask`` rows whose bodies don't self-gate via ``request_approval``."""
|
||||
return {
|
||||
r["name"]: True
|
||||
for r in bucket["ask"]
|
||||
if r.get("name") and r.get("kind") == "mcp"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue