chore: remove unused dead code
This commit is contained in:
@@ -311,7 +311,6 @@ class AgentLoop:
|
||||
self._running = False
|
||||
self._mcp_servers = mcp_servers or {}
|
||||
self._mcp_stacks: dict[str, AsyncExitStack] = {}
|
||||
self._mcp_connected = False
|
||||
self._mcp_connecting = False
|
||||
self._active_tasks: dict[str, list[asyncio.Task]] = {} # session_key -> tasks
|
||||
self._background_tasks: list[asyncio.Task] = []
|
||||
|
||||
@@ -526,8 +526,6 @@ class MCPToolWrapper(_MCPWrapperBase):
|
||||
f"(MCP tool returned malformed content: {type(exc).__name__})"
|
||||
)
|
||||
|
||||
return "(MCP tool call failed)" # Unreachable, but satisfies type checkers
|
||||
|
||||
def _render_call_result(self, content: Any, arguments: Mapping[str, Any]) -> str:
|
||||
"""Turn MCP content blocks into a tool result string.
|
||||
|
||||
@@ -679,8 +677,6 @@ class MCPResourceWrapper(_MCPWrapperBase):
|
||||
parts.append(str(block))
|
||||
return "\n".join(parts) or "(no output)"
|
||||
|
||||
return "(MCP resource read failed)" # Unreachable
|
||||
|
||||
|
||||
class MCPPromptWrapper(_MCPWrapperBase):
|
||||
"""Wraps an MCP prompt as a read-only nanobot Tool."""
|
||||
@@ -815,8 +811,6 @@ class MCPPromptWrapper(_MCPWrapperBase):
|
||||
parts.append(str(content))
|
||||
return "\n".join(parts) or "(no output)"
|
||||
|
||||
return "(MCP prompt call failed)" # Unreachable
|
||||
|
||||
|
||||
async def connect_mcp_servers(
|
||||
mcp_servers: dict, registry: ToolRegistry
|
||||
@@ -1140,17 +1134,14 @@ async def connect_missing_servers(state: Any, registry: ToolRegistry) -> None:
|
||||
connected = await connect_mcp_servers(missing_servers, registry)
|
||||
state._mcp_stacks.update(connected)
|
||||
_attach_reconnect_handlers(state, registry, connected)
|
||||
state._mcp_connected = bool(state._mcp_stacks)
|
||||
if connected:
|
||||
logger.info("MCP connected servers: {}", sorted(connected))
|
||||
else:
|
||||
logger.warning("No MCP servers connected successfully (will retry next message)")
|
||||
except asyncio.CancelledError:
|
||||
logger.warning("MCP connection cancelled (will retry next message)")
|
||||
state._mcp_connected = bool(state._mcp_stacks)
|
||||
except BaseException as e:
|
||||
logger.warning("Failed to connect MCP servers (will retry next message): {}", e)
|
||||
state._mcp_connected = bool(state._mcp_stacks)
|
||||
finally:
|
||||
state._mcp_connecting = False
|
||||
|
||||
@@ -1202,7 +1193,6 @@ async def reload_servers(state: Any, registry: ToolRegistry) -> dict[str, Any]:
|
||||
state._mcp_stacks.update(connected)
|
||||
_attach_reconnect_handlers(state, registry, connected)
|
||||
|
||||
state._mcp_connected = bool(state._mcp_stacks)
|
||||
failed = sorted(set(to_connect) - set(connected))
|
||||
unchanged = not removed and not added and not changed and not retry_missing
|
||||
ok = not failed
|
||||
@@ -1356,7 +1346,6 @@ async def _refresh_terminated_server(
|
||||
connected = await connect_mcp_servers({server_name: cfg}, registry)
|
||||
state._mcp_stacks.update(connected)
|
||||
_attach_reconnect_handlers(state, registry, connected)
|
||||
state._mcp_connected = bool(state._mcp_stacks)
|
||||
if server_name not in connected:
|
||||
logger.warning("MCP server '{}' reconnect failed after session termination", server_name)
|
||||
return None
|
||||
|
||||
@@ -1395,25 +1395,6 @@ async def _openai_images_from_payload(
|
||||
return images
|
||||
|
||||
|
||||
def _codex_responses_images_from_payload(payload: dict[str, Any]) -> list[str]:
|
||||
"""Extract images from Codex Responses API ``image_generation_call`` output."""
|
||||
images: list[str] = []
|
||||
for item in payload.get("output") or []:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
if item.get("type") != "image_generation_call":
|
||||
continue
|
||||
result = item.get("result")
|
||||
if isinstance(result, str):
|
||||
images.append(result if result.startswith("data:image/") else _b64_image_data_url(result))
|
||||
continue
|
||||
if isinstance(result, dict):
|
||||
image_url = result.get("image_url") or result.get("image") or ""
|
||||
if isinstance(image_url, str):
|
||||
images.append(image_url if image_url.startswith("data:image/") else _b64_image_data_url(image_url))
|
||||
return images
|
||||
|
||||
|
||||
async def _parse_codex_sse_images(
|
||||
response: httpx.Response,
|
||||
) -> tuple[list[str], str]:
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
|
||||
from nanobot.providers.base import LLMProvider
|
||||
@@ -12,11 +11,3 @@ from nanobot.providers.base import LLMProvider
|
||||
class LLMRuntime:
|
||||
provider: LLMProvider
|
||||
model: str
|
||||
|
||||
|
||||
LLMRuntimeResolver = Callable[[], LLMRuntime]
|
||||
|
||||
|
||||
def static_llm_runtime(provider: LLMProvider, model: str) -> LLMRuntimeResolver:
|
||||
runtime = LLMRuntime(provider=provider, model=model)
|
||||
return lambda: runtime
|
||||
|
||||
@@ -107,10 +107,6 @@ def parse_request_path(path_with_query: str) -> tuple[str, QueryParams]:
|
||||
return path, parse_qs(parsed.query, keep_blank_values=True)
|
||||
|
||||
|
||||
def normalize_http_path(path_with_query: str) -> str:
|
||||
return parse_request_path(path_with_query)[0]
|
||||
|
||||
|
||||
def parse_query(path_with_query: str) -> QueryParams:
|
||||
return parse_request_path(path_with_query)[1]
|
||||
|
||||
|
||||
@@ -131,7 +131,6 @@ async def test_connect_mcp_retries_when_no_servers_connect(tmp_path, monkeypatch
|
||||
await loop._connect_mcp()
|
||||
|
||||
assert attempts == 2
|
||||
assert loop._mcp_connected is False
|
||||
assert loop._mcp_stacks == {}
|
||||
|
||||
|
||||
|
||||
@@ -43,9 +43,6 @@ from nanobot.webui.http_utils import (
|
||||
from nanobot.webui.http_utils import (
|
||||
normalize_config_path as _normalize_config_path,
|
||||
)
|
||||
from nanobot.webui.http_utils import (
|
||||
normalize_http_path as _normalize_http_path,
|
||||
)
|
||||
from nanobot.webui.http_utils import (
|
||||
parse_query as _parse_query,
|
||||
)
|
||||
@@ -227,15 +224,15 @@ def _sent_ws_payloads(mock_ws: AsyncMock) -> list[dict[str, Any]]:
|
||||
return [json.loads(call.args[0]) for call in mock_ws.send.await_args_list]
|
||||
|
||||
|
||||
def test_normalize_http_path_strips_trailing_slash_except_root() -> None:
|
||||
assert _normalize_http_path("/chat/") == "/chat"
|
||||
assert _normalize_http_path("/chat?x=1") == "/chat"
|
||||
assert _normalize_http_path("/") == "/"
|
||||
def test_parse_request_path_strips_trailing_slash_except_root() -> None:
|
||||
assert _parse_request_path("/chat/")[0] == "/chat"
|
||||
assert _parse_request_path("/chat?x=1")[0] == "/chat"
|
||||
assert _parse_request_path("/")[0] == "/"
|
||||
|
||||
|
||||
def test_parse_request_path_matches_normalize_and_query() -> None:
|
||||
def test_parse_request_path_matches_query() -> None:
|
||||
path, query = _parse_request_path("/ws/?token=secret&client_id=u1")
|
||||
assert path == _normalize_http_path("/ws/?token=secret&client_id=u1")
|
||||
assert path == "/ws"
|
||||
assert query == _parse_query("/ws/?token=secret&client_id=u1")
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { logoFallbackUrls } from "@/lib/provider-brand";
|
||||
import type { CliAppInfo, McpPresetInfo } from "@/lib/types";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export type CliAppMentionSegment =
|
||||
type CliAppMentionSegment =
|
||||
| { kind: "text"; text: string }
|
||||
| { kind: "cli"; text: string; app: CliAppInfo };
|
||||
|
||||
@@ -36,42 +36,6 @@ export function mcpPresetInitials(preset: Pick<McpPresetInfo, "name" | "display_
|
||||
);
|
||||
}
|
||||
|
||||
export function splitCliAppMentionSegments(
|
||||
value: string,
|
||||
cliApps: CliAppInfo[],
|
||||
): CliAppMentionSegment[] {
|
||||
if (!value || cliApps.length === 0) return value ? [{ kind: "text", text: value }] : [];
|
||||
const appsByName = new Map(
|
||||
cliApps
|
||||
.filter((app) => app.installed)
|
||||
.map((app) => [app.name.toLowerCase(), app]),
|
||||
);
|
||||
if (appsByName.size === 0) return [{ kind: "text", text: value }];
|
||||
|
||||
const segments: CliAppMentionSegment[] = [];
|
||||
const mentionRe = /(^|[\s([{])@([a-z0-9_-]+)\b/gi;
|
||||
let cursor = 0;
|
||||
let match: RegExpExecArray | null;
|
||||
while ((match = mentionRe.exec(value)) !== null) {
|
||||
const prefix = match[1] ?? "";
|
||||
const name = match[2] ?? "";
|
||||
const app = appsByName.get(name.toLowerCase());
|
||||
if (!app) continue;
|
||||
|
||||
const mentionStart = match.index + prefix.length;
|
||||
const mentionEnd = mentionStart + name.length + 1;
|
||||
if (mentionStart > cursor) {
|
||||
segments.push({ kind: "text", text: value.slice(cursor, mentionStart) });
|
||||
}
|
||||
segments.push({ kind: "cli", text: value.slice(mentionStart, mentionEnd), app });
|
||||
cursor = mentionEnd;
|
||||
}
|
||||
if (cursor < value.length) {
|
||||
segments.push({ kind: "text", text: value.slice(cursor) });
|
||||
}
|
||||
return segments.length ? segments : [{ kind: "text", text: value }];
|
||||
}
|
||||
|
||||
export function splitCapabilityMentionSegments(
|
||||
value: string,
|
||||
cliApps: CliAppInfo[],
|
||||
|
||||
@@ -19,21 +19,6 @@ interface ThreadMessagesProps {
|
||||
|
||||
export type DisplayUnit = TurnUnit;
|
||||
|
||||
/** True when this unit index is the last assistant text slice before the next user message (or end of thread). */
|
||||
export function isFinalAssistantSliceBeforeNextUser(
|
||||
units: DisplayUnit[],
|
||||
index: number,
|
||||
): boolean {
|
||||
const u = units[index];
|
||||
if (u.type !== "message" || u.message.role !== "assistant") return true;
|
||||
for (let j = index + 1; j < units.length; j++) {
|
||||
const v = units[j];
|
||||
if (v.type === "message" && v.message.role === "user") break;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function buildDisplayUnits(
|
||||
messages: UIMessage[],
|
||||
isStreaming = false,
|
||||
|
||||
@@ -57,19 +57,6 @@ export function readStoredLocale(): SupportedLocale | null {
|
||||
}
|
||||
}
|
||||
|
||||
export function detectNavigatorLocale(): SupportedLocale {
|
||||
if (typeof navigator === "undefined") return defaultLocale;
|
||||
const candidates = [
|
||||
...(navigator.languages ?? []),
|
||||
navigator.language,
|
||||
].filter(Boolean);
|
||||
for (const locale of candidates) {
|
||||
const normalized = normalizeLocale(locale);
|
||||
if (normalized) return normalized;
|
||||
}
|
||||
return defaultLocale;
|
||||
}
|
||||
|
||||
export function resolveInitialLocale(): SupportedLocale {
|
||||
return readStoredLocale() ?? defaultLocale;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
} from "@/workers/imageEncode.worker";
|
||||
|
||||
export type { EncodeResponse, EncodeSuccess, EncodeFailure } from "@/workers/imageEncode.worker";
|
||||
export { TARGET_MAX_BYTES } from "@/workers/imageEncode.worker";
|
||||
|
||||
type Pending = {
|
||||
resolve: (r: EncodeResponse) => void;
|
||||
@@ -82,16 +81,3 @@ export async function encodeImage(file: File): Promise<EncodeResponse> {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Release the singleton Worker (tests / teardown). */
|
||||
export function disposeImageEncoder(): void {
|
||||
if (worker) {
|
||||
worker.terminate();
|
||||
worker = null;
|
||||
}
|
||||
bootAttempted = false;
|
||||
for (const [, entry] of pending) {
|
||||
entry.reject(new Error("image encoder disposed"));
|
||||
}
|
||||
pending.clear();
|
||||
}
|
||||
|
||||
@@ -1,26 +1,5 @@
|
||||
import type { ToolProgressEvent } from "@/lib/types";
|
||||
|
||||
/** Drop duplicate tool_call objects (same id or identical formatted trace). */
|
||||
export function dedupeToolCallsForUi(calls: unknown): unknown[] {
|
||||
if (!Array.isArray(calls) || calls.length === 0) return [];
|
||||
const seen = new Set<string>();
|
||||
const out: unknown[] = [];
|
||||
for (const c of calls) {
|
||||
let key: string | null = null;
|
||||
if (c && typeof c === "object" && "id" in c) {
|
||||
const id = (c as { id?: unknown }).id;
|
||||
if (typeof id === "string" && id.length > 0) key = `id:${id}`;
|
||||
}
|
||||
if (key == null) {
|
||||
key = formatToolCallTrace(c) ?? "";
|
||||
}
|
||||
if (!key || seen.has(key)) continue;
|
||||
seen.add(key);
|
||||
out.push(c);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export function formatToolCallTrace(call: unknown): string | null {
|
||||
if (!call || typeof call !== "object") return null;
|
||||
const item = call as {
|
||||
|
||||
Reference in New Issue
Block a user