Skip to content

Commit fbcc89f

Browse files
committed
refactor(omp): isolate host probes from room MCP lifecycle
1 parent 5f1c908 commit fbcc89f

2 files changed

Lines changed: 55 additions & 53 deletions

File tree

‎docs/acp.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,8 @@ may refresh native provider metadata; it does not prove authentication or
251251
inference entitlement. Cancellation propagates. Failed physical cleanup raises
252252
`CleanupIncompleteError` and stays owned by the adapter; retain the instance and
253253
retry `await adapter.cleanup_all()` before discarding it.
254+
Whole-adapter cleanup waits for probe cleanup and every room teardown before
255+
reporting their failures; each unfinished owner remains available for retry.
254256
CLI probes own an isolated POSIX process group or a Windows Job from launch,
255257
including descendants that inherit it after their launcher exits. Cleanup waits
256258
until no member is running before releasing probe custody or provider credentials.

‎src/band/adapters/omp.py‎

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -218,59 +218,6 @@ def model_selection(self) -> ModelSelection:
218218
def _host_tools(self) -> list[dict[str, JsonValue]]:
219219
return self._host_schemas
220220

221-
def _build_host_tools(self) -> list[dict[str, JsonValue]]:
222-
definitions = list(
223-
iter_tool_definitions(
224-
capabilities=self.features.capabilities | {Capability.CONTACTS}
225-
)
226-
)
227-
definitions = filter_tool_schemas(
228-
definitions,
229-
self.features,
230-
get_name=lambda item: item.name,
231-
get_category=lambda item: get_band_tool_category(item.name),
232-
)
233-
tools: list[dict[str, JsonValue]] = []
234-
if self.config.inject_band_tools:
235-
tools.extend(
236-
{
237-
"name": item.name,
238-
"description": get_tool_description(item.name),
239-
"parameters": platform_args_schema(item.name).model_json_schema(),
240-
"loadMode": "essential",
241-
}
242-
for item in definitions
243-
)
244-
for schema in custom_tools_to_schemas(self._custom_tools, "openai"):
245-
function = schema["function"]
246-
tools.append(
247-
{
248-
"name": function["name"],
249-
"description": function.get("description", ""),
250-
"parameters": function["parameters"],
251-
"loadMode": "essential",
252-
}
253-
)
254-
names = [tool["name"] for tool in tools]
255-
if len(set(names)) != len(names):
256-
raise ValueError("OMP host tools must have unique names")
257-
return tools
258-
259-
def _spawn_env(self) -> dict[str, str] | None:
260-
return omp_runtime_env(
261-
env=self.config.env,
262-
model=self.config.model,
263-
api_key=self.config.api_key,
264-
)
265-
266-
def _spawn_command(self, workspace: str | None) -> list[str]:
267-
command = finalize_omp_command(
268-
self.config.command,
269-
model=self.config.model,
270-
approval_mode=self.config.approval_mode,
271-
)
272-
return omp_command_in_workspace(command, workspace) if workspace else command
273-
274221
async def probe_models(self, *, timeout_s: float = 60.0) -> ModelCatalog:
275222
"""Discover configured OMP models without a Band room or inference.
276223
@@ -330,6 +277,59 @@ async def close() -> None:
330277

331278
return await owner.run(discover, timeout_s=timeout_s)
332279

280+
def _build_host_tools(self) -> list[dict[str, JsonValue]]:
281+
definitions = list(
282+
iter_tool_definitions(
283+
capabilities=self.features.capabilities | {Capability.CONTACTS}
284+
)
285+
)
286+
definitions = filter_tool_schemas(
287+
definitions,
288+
self.features,
289+
get_name=lambda item: item.name,
290+
get_category=lambda item: get_band_tool_category(item.name),
291+
)
292+
tools: list[dict[str, JsonValue]] = []
293+
if self.config.inject_band_tools:
294+
tools.extend(
295+
{
296+
"name": item.name,
297+
"description": get_tool_description(item.name),
298+
"parameters": platform_args_schema(item.name).model_json_schema(),
299+
"loadMode": "essential",
300+
}
301+
for item in definitions
302+
)
303+
for schema in custom_tools_to_schemas(self._custom_tools, "openai"):
304+
function = schema["function"]
305+
tools.append(
306+
{
307+
"name": function["name"],
308+
"description": function.get("description", ""),
309+
"parameters": function["parameters"],
310+
"loadMode": "essential",
311+
}
312+
)
313+
names = [tool["name"] for tool in tools]
314+
if len(set(names)) != len(names):
315+
raise ValueError("OMP host tools must have unique names")
316+
return tools
317+
318+
def _spawn_env(self) -> dict[str, str] | None:
319+
return omp_runtime_env(
320+
env=self.config.env,
321+
model=self.config.model,
322+
api_key=self.config.api_key,
323+
)
324+
325+
def _spawn_command(self, workspace: str | None) -> list[str]:
326+
command = finalize_omp_command(
327+
self.config.command,
328+
model=self.config.model,
329+
approval_mode=self.config.approval_mode,
330+
)
331+
return omp_command_in_workspace(command, workspace) if workspace else command
332+
333333
async def _open_room(self, room_id: str, history: OmpSessionState) -> OmpRoom:
334334
workspace = self._workspaces.claim(room_id)
335335
resources = ExitStack()

0 commit comments

Comments
 (0)