style: unify code formatting and import order

- Remove trailing whitespace and normalize blank lines
- Unify string quotes and line breaks for long lines
- Sort imports alphabetically across modules
This commit is contained in:
JK_Lu
2026-02-28 20:55:43 +08:00
parent bfc2fa88f3
commit 977ca725f2
33 changed files with 574 additions and 581 deletions

View File

@@ -1,7 +1,7 @@
"""Agent core module.""" """Agent core module."""
from nanobot.agent.loop import AgentLoop
from nanobot.agent.context import ContextBuilder from nanobot.agent.context import ContextBuilder
from nanobot.agent.loop import AgentLoop
from nanobot.agent.memory import MemoryStore from nanobot.agent.memory import MemoryStore
from nanobot.agent.skills import SkillsLoader from nanobot.agent.skills import SkillsLoader

View File

@@ -134,7 +134,7 @@ class SkillsLoader:
if missing: if missing:
lines.append(f" <requires>{escape_xml(missing)}</requires>") lines.append(f" <requires>{escape_xml(missing)}</requires>")
lines.append(f" </skill>") lines.append(" </skill>")
lines.append("</skills>") lines.append("</skills>")
return "\n".join(lines) return "\n".join(lines)

View File

@@ -8,13 +8,14 @@ from typing import Any
from loguru import logger from loguru import logger
from nanobot.agent.tools.filesystem import EditFileTool, ListDirTool, ReadFileTool, WriteFileTool
from nanobot.agent.tools.registry import ToolRegistry
from nanobot.agent.tools.shell import ExecTool
from nanobot.agent.tools.web import WebFetchTool, WebSearchTool
from nanobot.bus.events import InboundMessage from nanobot.bus.events import InboundMessage
from nanobot.bus.queue import MessageBus from nanobot.bus.queue import MessageBus
from nanobot.config.schema import ExecToolConfig
from nanobot.providers.base import LLMProvider from nanobot.providers.base import LLMProvider
from nanobot.agent.tools.registry import ToolRegistry
from nanobot.agent.tools.filesystem import ReadFileTool, WriteFileTool, EditFileTool, ListDirTool
from nanobot.agent.tools.shell import ExecTool
from nanobot.agent.tools.web import WebSearchTool, WebFetchTool
class SubagentManager: class SubagentManager:
@@ -206,8 +207,8 @@ Summarize this naturally for the user. Keep it brief (1-2 sentences). Do not men
def _build_subagent_prompt(self, task: str) -> str: def _build_subagent_prompt(self, task: str) -> str:
"""Build a focused system prompt for the subagent.""" """Build a focused system prompt for the subagent."""
from datetime import datetime
import time as _time import time as _time
from datetime import datetime
now = datetime.now().strftime("%Y-%m-%d %H:%M (%A)") now = datetime.now().strftime("%Y-%m-%d %H:%M (%A)")
tz = _time.strftime("%Z") or "UTC" tz = _time.strftime("%Z") or "UTC"

View File

@@ -84,10 +84,12 @@ class Tool(ABC):
errors.append(f"missing required {path + '.' + k if path else k}") errors.append(f"missing required {path + '.' + k if path else k}")
for k, v in val.items(): for k, v in val.items():
if k in props: if k in props:
errors.extend(self._validate(v, props[k], path + '.' + k if path else k)) errors.extend(self._validate(v, props[k], path + "." + k if path else k))
if t == "array" and "items" in schema: if t == "array" and "items" in schema:
for i, item in enumerate(val): for i, item in enumerate(val):
errors.extend(self._validate(item, schema["items"], f"{path}[{i}]" if path else f"[{i}]")) errors.extend(
self._validate(item, schema["items"], f"{path}[{i}]" if path else f"[{i}]")
)
return errors return errors
def to_schema(self) -> dict[str, Any]: def to_schema(self) -> dict[str, Any]:
@@ -98,5 +100,5 @@ class Tool(ABC):
"name": self.name, "name": self.name,
"description": self.description, "description": self.description,
"parameters": self.parameters, "parameters": self.parameters,
} },
} }

View File

@@ -36,34 +36,28 @@ class CronTool(Tool):
"action": { "action": {
"type": "string", "type": "string",
"enum": ["add", "list", "remove"], "enum": ["add", "list", "remove"],
"description": "Action to perform" "description": "Action to perform",
},
"message": {
"type": "string",
"description": "Reminder message (for add)"
}, },
"message": {"type": "string", "description": "Reminder message (for add)"},
"every_seconds": { "every_seconds": {
"type": "integer", "type": "integer",
"description": "Interval in seconds (for recurring tasks)" "description": "Interval in seconds (for recurring tasks)",
}, },
"cron_expr": { "cron_expr": {
"type": "string", "type": "string",
"description": "Cron expression like '0 9 * * *' (for scheduled tasks)" "description": "Cron expression like '0 9 * * *' (for scheduled tasks)",
}, },
"tz": { "tz": {
"type": "string", "type": "string",
"description": "IANA timezone for cron expressions (e.g. 'America/Vancouver')" "description": "IANA timezone for cron expressions (e.g. 'America/Vancouver')",
}, },
"at": { "at": {
"type": "string", "type": "string",
"description": "ISO datetime for one-time execution (e.g. '2026-02-12T10:30:00')" "description": "ISO datetime for one-time execution (e.g. '2026-02-12T10:30:00')",
}, },
"job_id": { "job_id": {"type": "string", "description": "Job ID (for remove)"},
"type": "string",
"description": "Job ID (for remove)"
}
}, },
"required": ["action"] "required": ["action"],
} }
async def execute( async def execute(
@@ -75,7 +69,7 @@ class CronTool(Tool):
tz: str | None = None, tz: str | None = None,
at: str | None = None, at: str | None = None,
job_id: str | None = None, job_id: str | None = None,
**kwargs: Any **kwargs: Any,
) -> str: ) -> str:
if action == "add": if action == "add":
return self._add_job(message, every_seconds, cron_expr, tz, at) return self._add_job(message, every_seconds, cron_expr, tz, at)
@@ -101,6 +95,7 @@ class CronTool(Tool):
return "Error: tz can only be used with cron_expr" return "Error: tz can only be used with cron_expr"
if tz: if tz:
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
try: try:
ZoneInfo(tz) ZoneInfo(tz)
except (KeyError, Exception): except (KeyError, Exception):
@@ -114,6 +109,7 @@ class CronTool(Tool):
schedule = CronSchedule(kind="cron", expr=cron_expr, tz=tz) schedule = CronSchedule(kind="cron", expr=cron_expr, tz=tz)
elif at: elif at:
from datetime import datetime from datetime import datetime
dt = datetime.fromisoformat(at) dt = datetime.fromisoformat(at)
at_ms = int(dt.timestamp() * 1000) at_ms = int(dt.timestamp() * 1000)
schedule = CronSchedule(kind="at", at_ms=at_ms) schedule = CronSchedule(kind="at", at_ms=at_ms)

View File

@@ -7,7 +7,9 @@ from typing import Any
from nanobot.agent.tools.base import Tool from nanobot.agent.tools.base import Tool
def _resolve_path(path: str, workspace: Path | None = None, allowed_dir: Path | None = None) -> Path: def _resolve_path(
path: str, workspace: Path | None = None, allowed_dir: Path | None = None
) -> Path:
"""Resolve path against workspace (if relative) and enforce directory restriction.""" """Resolve path against workspace (if relative) and enforce directory restriction."""
p = Path(path).expanduser() p = Path(path).expanduser()
if not p.is_absolute() and workspace: if not p.is_absolute() and workspace:
@@ -40,13 +42,8 @@ class ReadFileTool(Tool):
def parameters(self) -> dict[str, Any]: def parameters(self) -> dict[str, Any]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {"path": {"type": "string", "description": "The file path to read"}},
"path": { "required": ["path"],
"type": "string",
"description": "The file path to read"
}
},
"required": ["path"]
} }
async def execute(self, path: str, **kwargs: Any) -> str: async def execute(self, path: str, **kwargs: Any) -> str:
@@ -85,16 +82,10 @@ class WriteFileTool(Tool):
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
"path": { "path": {"type": "string", "description": "The file path to write to"},
"type": "string", "content": {"type": "string", "description": "The content to write"},
"description": "The file path to write to"
},
"content": {
"type": "string",
"description": "The content to write"
}
}, },
"required": ["path", "content"] "required": ["path", "content"],
} }
async def execute(self, path: str, content: str, **kwargs: Any) -> str: async def execute(self, path: str, content: str, **kwargs: Any) -> str:
@@ -129,20 +120,11 @@ class EditFileTool(Tool):
return { return {
"type": "object", "type": "object",
"properties": { "properties": {
"path": { "path": {"type": "string", "description": "The file path to edit"},
"type": "string", "old_text": {"type": "string", "description": "The exact text to find and replace"},
"description": "The file path to edit" "new_text": {"type": "string", "description": "The text to replace with"},
},
"old_text": {
"type": "string",
"description": "The exact text to find and replace"
},
"new_text": {
"type": "string",
"description": "The text to replace with"
}
}, },
"required": ["path", "old_text", "new_text"] "required": ["path", "old_text", "new_text"],
} }
async def execute(self, path: str, old_text: str, new_text: str, **kwargs: Any) -> str: async def execute(self, path: str, old_text: str, new_text: str, **kwargs: Any) -> str:
@@ -184,13 +166,19 @@ class EditFileTool(Tool):
best_ratio, best_start = ratio, i best_ratio, best_start = ratio, i
if best_ratio > 0.5: if best_ratio > 0.5:
diff = "\n".join(difflib.unified_diff( diff = "\n".join(
old_lines, lines[best_start : best_start + window], difflib.unified_diff(
fromfile="old_text (provided)", tofile=f"{path} (actual, line {best_start + 1})", old_lines,
lineterm="", lines[best_start : best_start + window],
)) fromfile="old_text (provided)",
tofile=f"{path} (actual, line {best_start + 1})",
lineterm="",
)
)
return f"Error: old_text not found in {path}.\nBest match ({best_ratio:.0%} similar) at line {best_start + 1}:\n{diff}" return f"Error: old_text not found in {path}.\nBest match ({best_ratio:.0%} similar) at line {best_start + 1}:\n{diff}"
return f"Error: old_text not found in {path}. No similar text found. Verify the file content." return (
f"Error: old_text not found in {path}. No similar text found. Verify the file content."
)
class ListDirTool(Tool): class ListDirTool(Tool):
@@ -212,13 +200,8 @@ class ListDirTool(Tool):
def parameters(self) -> dict[str, Any]: def parameters(self) -> dict[str, Any]:
return { return {
"type": "object", "type": "object",
"properties": { "properties": {"path": {"type": "string", "description": "The directory path to list"}},
"path": { "required": ["path"],
"type": "string",
"description": "The directory path to list"
}
},
"required": ["path"]
} }
async def execute(self, path: str, **kwargs: Any) -> str: async def execute(self, path: str, **kwargs: Any) -> str:

View File

@@ -1,6 +1,6 @@
"""Spawn tool for creating background subagents.""" """Spawn tool for creating background subagents."""
from typing import Any, TYPE_CHECKING from typing import TYPE_CHECKING, Any
from nanobot.agent.tools.base import Tool from nanobot.agent.tools.base import Tool

View File

@@ -5,8 +5,8 @@ import json
import time import time
from typing import Any from typing import Any
from loguru import logger
import httpx import httpx
from loguru import logger
from nanobot.bus.events import OutboundMessage from nanobot.bus.events import OutboundMessage
from nanobot.bus.queue import MessageBus from nanobot.bus.queue import MessageBus
@@ -15,11 +15,11 @@ from nanobot.config.schema import DingTalkConfig
try: try:
from dingtalk_stream import ( from dingtalk_stream import (
DingTalkStreamClient, AckMessage,
Credential,
CallbackHandler, CallbackHandler,
CallbackMessage, CallbackMessage,
AckMessage, Credential,
DingTalkStreamClient,
) )
from dingtalk_stream.chatbot import ChatbotMessage from dingtalk_stream.chatbot import ChatbotMessage

View File

@@ -14,7 +14,6 @@ from nanobot.bus.queue import MessageBus
from nanobot.channels.base import BaseChannel from nanobot.channels.base import BaseChannel
from nanobot.config.schema import DiscordConfig from nanobot.config.schema import DiscordConfig
DISCORD_API_BASE = "https://discord.com/api/v10" DISCORD_API_BASE = "https://discord.com/api/v10"
MAX_ATTACHMENT_BYTES = 20 * 1024 * 1024 # 20MB MAX_ATTACHMENT_BYTES = 20 * 1024 * 1024 # 20MB
MAX_MESSAGE_LEN = 2000 # Discord message character limit MAX_MESSAGE_LEN = 2000 # Discord message character limit

View File

@@ -23,12 +23,11 @@ try:
CreateFileRequestBody, CreateFileRequestBody,
CreateImageRequest, CreateImageRequest,
CreateImageRequestBody, CreateImageRequestBody,
CreateMessageRequest,
CreateMessageRequestBody,
CreateMessageReactionRequest, CreateMessageReactionRequest,
CreateMessageReactionRequestBody, CreateMessageReactionRequestBody,
CreateMessageRequest,
CreateMessageRequestBody,
Emoji, Emoji,
GetFileRequest,
GetMessageResourceRequest, GetMessageResourceRequest,
P2ImMessageReceiveV1, P2ImMessageReceiveV1,
) )
@@ -313,7 +312,8 @@ class FeishuChannel(BaseChannel):
except Exception as e: except Exception as e:
logger.warning("Feishu WebSocket error: {}", e) logger.warning("Feishu WebSocket error: {}", e)
if self._running: if self._running:
import time; time.sleep(5) import time
time.sleep(5)
self._ws_thread = threading.Thread(target=run_ws, daemon=True) self._ws_thread = threading.Thread(target=run_ws, daemon=True)
self._ws_thread.start() self._ws_thread.start()
@@ -380,12 +380,13 @@ class FeishuChannel(BaseChannel):
@staticmethod @staticmethod
def _parse_md_table(table_text: str) -> dict | None: def _parse_md_table(table_text: str) -> dict | None:
"""Parse a markdown table into a Feishu table element.""" """Parse a markdown table into a Feishu table element."""
lines = [l.strip() for l in table_text.strip().split("\n") if l.strip()] lines = [_line.strip() for _line in table_text.strip().split("\n") if _line.strip()]
if len(lines) < 3: if len(lines) < 3:
return None return None
split = lambda l: [c.strip() for c in l.strip("|").split("|")] def split(_line: str) -> list[str]:
return [c.strip() for c in _line.strip("|").split("|")]
headers = split(lines[0]) headers = split(lines[0])
rows = [split(l) for l in lines[2:]] rows = [split(_line) for _line in lines[2:]]
columns = [{"tag": "column", "name": f"c{i}", "display_name": h, "width": "auto"} columns = [{"tag": "column", "name": f"c{i}", "display_name": h, "width": "auto"}
for i, h in enumerate(headers)] for i, h in enumerate(headers)]
return { return {

View File

@@ -12,10 +12,22 @@ try:
import nh3 import nh3
from mistune import create_markdown from mistune import create_markdown
from nio import ( from nio import (
AsyncClient, AsyncClientConfig, ContentRepositoryConfigError, AsyncClient,
DownloadError, InviteEvent, JoinError, MatrixRoom, MemoryDownloadResponse, AsyncClientConfig,
RoomEncryptedMedia, RoomMessage, RoomMessageMedia, RoomMessageText, ContentRepositoryConfigError,
RoomSendError, RoomTypingError, SyncError, UploadError, DownloadError,
InviteEvent,
JoinError,
MatrixRoom,
MemoryDownloadResponse,
RoomEncryptedMedia,
RoomMessage,
RoomMessageMedia,
RoomMessageText,
RoomSendError,
RoomTypingError,
SyncError,
UploadError,
) )
from nio.crypto.attachments import decrypt_attachment from nio.crypto.attachments import decrypt_attachment
from nio.exceptions import EncryptionError from nio.exceptions import EncryptionError

View File

@@ -5,11 +5,10 @@ import re
from typing import Any from typing import Any
from loguru import logger from loguru import logger
from slack_sdk.socket_mode.websockets import SocketModeClient
from slack_sdk.socket_mode.request import SocketModeRequest from slack_sdk.socket_mode.request import SocketModeRequest
from slack_sdk.socket_mode.response import SocketModeResponse from slack_sdk.socket_mode.response import SocketModeResponse
from slack_sdk.socket_mode.websockets import SocketModeClient
from slack_sdk.web.async_client import AsyncWebClient from slack_sdk.web.async_client import AsyncWebClient
from slackify_markdown import slackify_markdown from slackify_markdown import slackify_markdown
from nanobot.bus.events import OutboundMessage from nanobot.bus.events import OutboundMessage

View File

@@ -4,9 +4,10 @@ from __future__ import annotations
import asyncio import asyncio
import re import re
from loguru import logger from loguru import logger
from telegram import BotCommand, Update, ReplyParameters from telegram import BotCommand, ReplyParameters, Update
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
from telegram.request import HTTPXRequest from telegram.request import HTTPXRequest
from nanobot.bus.events import OutboundMessage from nanobot.bus.events import OutboundMessage

View File

@@ -3,7 +3,6 @@
import asyncio import asyncio
import json import json
from collections import OrderedDict from collections import OrderedDict
from typing import Any
from loguru import logger from loguru import logger

View File

@@ -2,23 +2,22 @@
import asyncio import asyncio
import os import os
import signal
from pathlib import Path
import select import select
import signal
import sys import sys
from pathlib import Path
import typer import typer
from prompt_toolkit import PromptSession
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.history import FileHistory
from prompt_toolkit.patch_stdout import patch_stdout
from rich.console import Console from rich.console import Console
from rich.markdown import Markdown from rich.markdown import Markdown
from rich.table import Table from rich.table import Table
from rich.text import Text from rich.text import Text
from prompt_toolkit import PromptSession from nanobot import __logo__, __version__
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.history import FileHistory
from prompt_toolkit.patch_stdout import patch_stdout
from nanobot import __version__, __logo__
from nanobot.config.schema import Config from nanobot.config.schema import Config
from nanobot.utils.helpers import sync_workspace_templates from nanobot.utils.helpers import sync_workspace_templates
@@ -201,9 +200,9 @@ def onboard():
def _make_provider(config: Config): def _make_provider(config: Config):
"""Create the appropriate LLM provider from config.""" """Create the appropriate LLM provider from config."""
from nanobot.providers.custom_provider import CustomProvider
from nanobot.providers.litellm_provider import LiteLLMProvider from nanobot.providers.litellm_provider import LiteLLMProvider
from nanobot.providers.openai_codex_provider import OpenAICodexProvider from nanobot.providers.openai_codex_provider import OpenAICodexProvider
from nanobot.providers.custom_provider import CustomProvider
model = config.agents.defaults.model model = config.agents.defaults.model
provider_name = config.get_provider_name(model) provider_name = config.get_provider_name(model)
@@ -248,14 +247,14 @@ def gateway(
verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"), verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
): ):
"""Start the nanobot gateway.""" """Start the nanobot gateway."""
from nanobot.config.loader import load_config, get_data_dir
from nanobot.bus.queue import MessageBus
from nanobot.agent.loop import AgentLoop from nanobot.agent.loop import AgentLoop
from nanobot.bus.queue import MessageBus
from nanobot.channels.manager import ChannelManager from nanobot.channels.manager import ChannelManager
from nanobot.session.manager import SessionManager from nanobot.config.loader import get_data_dir, load_config
from nanobot.cron.service import CronService from nanobot.cron.service import CronService
from nanobot.cron.types import CronJob from nanobot.cron.types import CronJob
from nanobot.heartbeat.service import HeartbeatService from nanobot.heartbeat.service import HeartbeatService
from nanobot.session.manager import SessionManager
if verbose: if verbose:
import logging import logging
@@ -411,12 +410,13 @@ def agent(
logs: bool = typer.Option(False, "--logs/--no-logs", help="Show nanobot runtime logs during chat"), logs: bool = typer.Option(False, "--logs/--no-logs", help="Show nanobot runtime logs during chat"),
): ):
"""Interact with the agent directly.""" """Interact with the agent directly."""
from nanobot.config.loader import load_config, get_data_dir
from nanobot.bus.queue import MessageBus
from nanobot.agent.loop import AgentLoop
from nanobot.cron.service import CronService
from loguru import logger from loguru import logger
from nanobot.agent.loop import AgentLoop
from nanobot.bus.queue import MessageBus
from nanobot.config.loader import get_data_dir, load_config
from nanobot.cron.service import CronService
config = load_config() config = load_config()
sync_workspace_templates(config.workspace_path) sync_workspace_templates(config.workspace_path)
@@ -735,6 +735,7 @@ def _get_bridge_dir() -> Path:
def channels_login(): def channels_login():
"""Link device via QR code.""" """Link device via QR code."""
import subprocess import subprocess
from nanobot.config.loader import load_config from nanobot.config.loader import load_config
config = load_config() config = load_config()
@@ -913,11 +914,12 @@ def cron_run(
): ):
"""Manually run a job.""" """Manually run a job."""
from loguru import logger from loguru import logger
from nanobot.config.loader import load_config, get_data_dir
from nanobot.agent.loop import AgentLoop
from nanobot.bus.queue import MessageBus
from nanobot.config.loader import get_data_dir, load_config
from nanobot.cron.service import CronService from nanobot.cron.service import CronService
from nanobot.cron.types import CronJob from nanobot.cron.types import CronJob
from nanobot.bus.queue import MessageBus
from nanobot.agent.loop import AgentLoop
logger.disable("nanobot") logger.disable("nanobot")
config = load_config() config = load_config()
@@ -975,7 +977,7 @@ def cron_run(
@app.command() @app.command()
def status(): def status():
"""Show nanobot status.""" """Show nanobot status."""
from nanobot.config.loader import load_config, get_config_path from nanobot.config.loader import get_config_path, load_config
config_path = get_config_path() config_path = get_config_path()
config = load_config() config = load_config()

View File

@@ -1,6 +1,6 @@
"""Configuration module for nanobot.""" """Configuration module for nanobot."""
from nanobot.config.loader import load_config, get_config_path from nanobot.config.loader import get_config_path, load_config
from nanobot.config.schema import Config from nanobot.config.schema import Config
__all__ = ["Config", "load_config", "get_config_path"] __all__ = ["Config", "load_config", "get_config_path"]

View File

@@ -3,7 +3,7 @@
from pathlib import Path from pathlib import Path
from typing import Literal from typing import Literal
from pydantic import BaseModel, Field, ConfigDict from pydantic import BaseModel, ConfigDict, Field
from pydantic.alias_generators import to_camel from pydantic.alias_generators import to_camel
from pydantic_settings import BaseSettings from pydantic_settings import BaseSettings

View File

@@ -30,8 +30,9 @@ def _compute_next_run(schedule: CronSchedule, now_ms: int) -> int | None:
if schedule.kind == "cron" and schedule.expr: if schedule.kind == "cron" and schedule.expr:
try: try:
from croniter import croniter
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
from croniter import croniter
# Use caller-provided reference time for deterministic scheduling # Use caller-provided reference time for deterministic scheduling
base_time = now_ms / 1000 base_time = now_ms / 1000
tz = ZoneInfo(schedule.tz) if schedule.tz else datetime.now().astimezone().tzinfo tz = ZoneInfo(schedule.tz) if schedule.tz else datetime.now().astimezone().tzinfo

View File

@@ -1,19 +1,17 @@
"""LiteLLM provider implementation for multi-provider support.""" """LiteLLM provider implementation for multi-provider support."""
import json
import json_repair
import os import os
import secrets import secrets
import string import string
from typing import Any from typing import Any
import json_repair
import litellm import litellm
from litellm import acompletion from litellm import acompletion
from nanobot.providers.base import LLMProvider, LLMResponse, ToolCallRequest from nanobot.providers.base import LLMProvider, LLMResponse, ToolCallRequest
from nanobot.providers.registry import find_by_model, find_gateway from nanobot.providers.registry import find_by_model, find_gateway
# Standard OpenAI chat-completion message keys plus reasoning_content for # Standard OpenAI chat-completion message keys plus reasoning_content for
# thinking-enabled models (Kimi k2.5, DeepSeek-R1, etc.). # thinking-enabled models (Kimi k2.5, DeepSeek-R1, etc.).
_ALLOWED_MSG_KEYS = frozenset({"role", "content", "tool_calls", "tool_call_id", "name", "reasoning_content"}) _ALLOWED_MSG_KEYS = frozenset({"role", "content", "tool_calls", "tool_call_id", "name", "reasoning_content"})

View File

@@ -9,8 +9,8 @@ from typing import Any, AsyncGenerator
import httpx import httpx
from loguru import logger from loguru import logger
from oauth_cli_kit import get_token as get_codex_token from oauth_cli_kit import get_token as get_codex_token
from nanobot.providers.base import LLMProvider, LLMResponse, ToolCallRequest from nanobot.providers.base import LLMProvider, LLMResponse, ToolCallRequest
DEFAULT_CODEX_URL = "https://chatgpt.com/backend-api/codex/responses" DEFAULT_CODEX_URL = "https://chatgpt.com/backend-api/codex/responses"

View File

@@ -2,7 +2,6 @@
import os import os
from pathlib import Path from pathlib import Path
from typing import Any
import httpx import httpx
from loguru import logger from loguru import logger

View File

@@ -1,5 +1,5 @@
"""Session management module.""" """Session management module."""
from nanobot.session.manager import SessionManager, Session from nanobot.session.manager import Session, SessionManager
__all__ = ["SessionManager", "Session"] __all__ = ["SessionManager", "Session"]

View File

@@ -2,9 +2,9 @@
import json import json
import shutil import shutil
from pathlib import Path
from dataclasses import dataclass, field from dataclasses import dataclass, field
from datetime import datetime from datetime import datetime
from pathlib import Path
from typing import Any from typing import Any
from loguru import logger from loguru import logger

View File

@@ -1,5 +1,5 @@
"""Utility functions for nanobot.""" """Utility functions for nanobot."""
from nanobot.utils.helpers import ensure_dir, get_workspace_path, get_data_path from nanobot.utils.helpers import ensure_dir, get_data_path, get_workspace_path
__all__ = ["ensure_dir", "get_workspace_path", "get_data_path"] __all__ = ["ensure_dir", "get_workspace_path", "get_data_path"]

View File

@@ -1,8 +1,8 @@
"""Utility functions for nanobot.""" """Utility functions for nanobot."""
import re import re
from pathlib import Path
from datetime import datetime from datetime import datetime
from pathlib import Path
def ensure_dir(path: Path) -> Path: def ensure_dir(path: Path) -> Path: