refactor: root-package imports (svc/runtime/interfaces) and fix PYTHONPATH

- Rename platform/ to svc/ to avoid shadowing stdlib platform.
- Replace from oclaw.* with from svc/runtime/interfaces; update -m CLI paths.
- tests/conftest: prepend repo root to sys.path (no parent-folder package name).
- CI: paths and offline_eval script under repo root.
- Ops scripts: PYTHONPATH must be repo root for python -m runtime.* (fixes gateway/WhatsApp sidecar startup).
- Fix default oclaw.json path in tabular/file attachment limits; stabilize attachment test config.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-05-13 14:51:17 +08:00
parent 7941b27f58
commit 420abac9f1
405 changed files with 1316 additions and 1345 deletions

View file

@ -3,8 +3,8 @@ from __future__ import annotations
import hashlib
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.path_guard import resolve_workspace_path
from runtime.tools.base import ToolSpec
from runtime.tools.path_guard import resolve_workspace_path
def apply_patch_tool() -> ToolSpec:

View file

@ -4,8 +4,8 @@ import re
from typing import Any
from pathlib import Path
from oclaw.platform.files.attachment_assets import AttachmentAssetStore
from oclaw.runtime.tools.base import ToolSpec
from svc.files.attachment_assets import AttachmentAssetStore
from runtime.tools.base import ToolSpec
_ATTACHMENT_ID_RE = re.compile(r"^[a-f0-9]{64}$")

View file

@ -7,7 +7,7 @@ import urllib.parse
import urllib.request
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from runtime.tools.base import ToolSpec
_WEBPARSER_SSE_URL = "https://dashscope.aliyuncs.com/api/v1/mcps/WebParser/sse"
_UA = (

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.path_guard import resolve_workspace_path
from runtime.tools.base import ToolSpec
from runtime.tools.path_guard import resolve_workspace_path
def bulk_apply_patch_tool() -> ToolSpec:

View file

@ -10,9 +10,9 @@ from urllib import request as urllib_request
from PIL import Image
from oclaw.platform.files.attachment_assets import AttachmentAssetStore
from oclaw.runtime.operations.mcp_env import apply_gateway_mcp_env_to_os
from oclaw.runtime.tools.base import ToolSpec
from svc.files.attachment_assets import AttachmentAssetStore
from runtime.operations.mcp_env import apply_gateway_mcp_env_to_os
from runtime.tools.base import ToolSpec
def _to_image_bytes(resp_body: bytes, content_type: str) -> tuple[bytes, str]:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.public.local_sdk import get_local_adapter
from runtime.tools.base import ToolSpec
from runtime.tools.public.local_sdk import get_local_adapter
def delete_file_tool() -> ToolSpec:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.public.local_sdk import get_local_adapter
from runtime.tools.base import ToolSpec
from runtime.tools.public.local_sdk import get_local_adapter
def edit_file_tool() -> ToolSpec:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.public.local_sdk import get_local_adapter
from runtime.tools.base import ToolSpec
from runtime.tools.public.local_sdk import get_local_adapter
def get_cwd_tool() -> ToolSpec:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.public.local_sdk import get_local_adapter
from runtime.tools.base import ToolSpec
from runtime.tools.public.local_sdk import get_local_adapter
def get_env_tool() -> ToolSpec:

View file

@ -3,8 +3,8 @@ from __future__ import annotations
import subprocess
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.path_guard import resolve_workspace_path, sanitize_git_ref, truncate_text
from runtime.tools.base import ToolSpec
from runtime.tools.path_guard import resolve_workspace_path, sanitize_git_ref, truncate_text
def _git(command: str, *, cwd: str) -> dict[str, Any]:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.path_guard import resolve_workspace_path
from runtime.tools.base import ToolSpec
from runtime.tools.path_guard import resolve_workspace_path
def glob_tool() -> ToolSpec:

View file

@ -7,8 +7,8 @@ from typing import Any
from PIL import Image
from oclaw.platform.files.attachment_assets import AttachmentAssetStore
from oclaw.runtime.tools.base import ToolSpec
from svc.files.attachment_assets import AttachmentAssetStore
from runtime.tools.base import ToolSpec
def image_edit_tool() -> ToolSpec:

View file

@ -2,16 +2,16 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from runtime.tools.base import ToolSpec
def index_workspace_tool() -> ToolSpec:
def handler(args: dict[str, Any]) -> dict[str, Any]:
max_files = int(args.get("max_files") or 120)
try:
from oclaw.platform.persistence.sqlite_store import SqliteStore
from oclaw.platform.config.paths import db_path
from oclaw.runtime.tools.workspace_indexer import index_workspace
from svc.persistence.sqlite_store import SqliteStore
from svc.config.paths import db_path
from runtime.tools.workspace_indexer import index_workspace
store = SqliteStore(db_path())
st = index_workspace(store, max_files=max(1, min(max_files, 800)))

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.public.local_sdk import get_local_adapter
from runtime.tools.base import ToolSpec
from runtime.tools.public.local_sdk import get_local_adapter
def kill_process_tool() -> ToolSpec:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.public.local_sdk import get_local_adapter
from runtime.tools.base import ToolSpec
from runtime.tools.public.local_sdk import get_local_adapter
def list_directory_tool() -> ToolSpec:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.public.local_sdk import get_local_adapter
from runtime.tools.base import ToolSpec
from runtime.tools.public.local_sdk import get_local_adapter
def list_processes_tool() -> ToolSpec:

View file

@ -3,8 +3,8 @@ from __future__ import annotations
from pathlib import Path
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.path_guard import resolve_workspace_path
from runtime.tools.base import ToolSpec
from runtime.tools.path_guard import resolve_workspace_path
def list_workspace_tree_tool() -> ToolSpec:

View file

@ -9,7 +9,7 @@ from datetime import datetime, timezone
from pathlib import Path
from typing import Any
from oclaw.runtime.tools.path_guard import resolve_workspace_path, truncate_text
from runtime.tools.path_guard import resolve_workspace_path, truncate_text
@dataclass(frozen=True)
@ -80,14 +80,14 @@ class LocalAdapter:
dbp = str(os.getenv("OPS_ASSISTANT_DB_PATH") or "").strip()
try:
if not dbp:
from oclaw.platform.config.paths import db_path
from svc.config.paths import db_path
dbp = str(db_path() or "").strip()
except Exception:
dbp = ""
if dbp:
try:
from oclaw.platform.persistence.sqlite_store import SqliteStore
from svc.persistence.sqlite_store import SqliteStore
store = SqliteStore(dbp)
raw_db = str(store.get_setting("AIA_ENABLE_RUN_COMMAND") or "").strip()

View file

@ -5,8 +5,8 @@ import sys
from types import SimpleNamespace
from typing import Any, Callable
from oclaw.platform.config.paths import PROJECT_ROOT
from oclaw.runtime.tools.base import ToolSpec
from svc.config.paths import PROJECT_ROOT
from runtime.tools.base import ToolSpec
def _plugin_cfg() -> dict[str, Any]:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.public.local_sdk import get_local_adapter
from runtime.tools.base import ToolSpec
from runtime.tools.public.local_sdk import get_local_adapter
def mkdir_tool() -> ToolSpec:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.public.local_sdk import get_local_adapter
from runtime.tools.base import ToolSpec
from runtime.tools.public.local_sdk import get_local_adapter
def move_file_tool() -> ToolSpec:

View file

@ -3,8 +3,8 @@ from __future__ import annotations
from pathlib import Path
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.path_guard import resolve_workspace_path
from runtime.tools.base import ToolSpec
from runtime.tools.path_guard import resolve_workspace_path
def multi_edit_file_tool() -> ToolSpec:

View file

@ -2,14 +2,14 @@ from __future__ import annotations
from typing import Any
from oclaw.platform.files.attachment_assets import attachment_id_to_data_url
from oclaw.platform.llm.image_ocr_client import (
from svc.files.attachment_assets import attachment_id_to_data_url
from svc.llm.image_ocr_client import (
VISION_DESCRIBE_PROMPT_ZH,
VISION_OCR_EXTRACT_PROMPT_ZH,
send_ocr_image_messages,
vision_llm_backend_status,
)
from oclaw.runtime.tools.base import ToolSpec
from runtime.tools.base import ToolSpec
def query_image_attachment_tool() -> ToolSpec:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.platform.files.text_attachment_store import query_text_document
from oclaw.runtime.tools.base import ToolSpec
from svc.files.text_attachment_store import query_text_document
from runtime.tools.base import ToolSpec
def query_text_attachment_tool() -> ToolSpec:

View file

@ -8,14 +8,14 @@ import tempfile
from pathlib import Path
from typing import Any
from oclaw.platform.files.attachment_assets import AttachmentAssetStore
from oclaw.platform.files.text_attachment_store import (
from svc.files.attachment_assets import AttachmentAssetStore
from svc.files.text_attachment_store import (
DEFAULT_TEXT_CHUNK_OVERLAP,
DEFAULT_TEXT_CHUNK_SIZE,
save_text_document,
)
from oclaw.runtime.extensions.openai.api import OPENAI_DEFAULT_AUDIO_TRANSCRIPTION_MODEL
from oclaw.runtime.tools.base import ToolSpec
from runtime.extensions.openai.api import OPENAI_DEFAULT_AUDIO_TRANSCRIPTION_MODEL
from runtime.tools.base import ToolSpec
def _ffmpeg_exists() -> bool:

View file

@ -3,8 +3,8 @@ from __future__ import annotations
import hashlib
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.path_guard import resolve_workspace_path
from runtime.tools.base import ToolSpec
from runtime.tools.path_guard import resolve_workspace_path
def read_file_tool() -> ToolSpec:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.public.local_sdk import get_local_adapter
from runtime.tools.base import ToolSpec
from runtime.tools.public.local_sdk import get_local_adapter
def run_command_tool() -> ToolSpec:

View file

@ -4,8 +4,8 @@ import re
from pathlib import Path
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.path_guard import resolve_workspace_path, truncate_text
from runtime.tools.base import ToolSpec
from runtime.tools.path_guard import resolve_workspace_path, truncate_text
def search_files_context_tool() -> ToolSpec:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.public.local_sdk import get_local_adapter
from runtime.tools.base import ToolSpec
from runtime.tools.public.local_sdk import get_local_adapter
def search_files_tool() -> ToolSpec:

View file

@ -2,8 +2,8 @@ from __future__ import annotations
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.public.local_sdk import get_local_adapter
from runtime.tools.base import ToolSpec
from runtime.tools.public.local_sdk import get_local_adapter
def set_env_tool() -> ToolSpec:

View file

@ -3,16 +3,16 @@ from __future__ import annotations
from pathlib import Path
from typing import Any
from oclaw.platform.config.paths import db_path
from oclaw.platform.persistence.sqlite_store import SqliteStore
from oclaw.runtime.chat.tool_invocation_context import (
from svc.config.paths import db_path
from svc.persistence.sqlite_store import SqliteStore
from runtime.chat.tool_invocation_context import (
current_tool_lane_sessions,
current_tool_workspace_lane_role,
)
from oclaw.runtime.skill_installer import auto_install_skill_from_payload, install_skill_from_registry_archive
from oclaw.runtime.skills_market import get_market_adapter, normalize_skill_market_provider_setting
from oclaw.runtime.skills_workspace_lane import resolve_auto_install_parent
from oclaw.runtime.tools.base import ToolSpec
from runtime.skill_installer import auto_install_skill_from_payload, install_skill_from_registry_archive
from runtime.skills_market import get_market_adapter, normalize_skill_market_provider_setting
from runtime.skills_workspace_lane import resolve_auto_install_parent
from runtime.tools.base import ToolSpec
def _store() -> SqliteStore:

View file

@ -3,12 +3,12 @@ from __future__ import annotations
from pathlib import Path
from typing import Any
from oclaw.platform.config.paths import db_path
from oclaw.platform.persistence.sqlite_store import SqliteStore
from oclaw.runtime.skill_installer import install_skill_from_registry_archive
from oclaw.runtime.skills import default_skills_root
from oclaw.runtime.skills_market import get_market_adapter, normalize_skill_market_provider_setting
from oclaw.runtime.tools.base import ToolSpec
from svc.config.paths import db_path
from svc.persistence.sqlite_store import SqliteStore
from runtime.skill_installer import install_skill_from_registry_archive
from runtime.skills import default_skills_root
from runtime.skills_market import get_market_adapter, normalize_skill_market_provider_setting
from runtime.tools.base import ToolSpec
def _store() -> SqliteStore:

View file

@ -3,7 +3,7 @@ from __future__ import annotations
from datetime import datetime, timezone
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from runtime.tools.base import ToolSpec
def system_time_tool() -> ToolSpec:

View file

@ -2,13 +2,13 @@ from __future__ import annotations
from typing import Any
from oclaw.platform.files.tabular_attachment_store import (
from svc.files.tabular_attachment_store import (
aggregate_table,
analyze_table_full_scan,
query_table,
run_table_sql,
)
from oclaw.runtime.tools.base import ToolSpec
from runtime.tools.base import ToolSpec
def query_tabular_attachment_tool() -> ToolSpec:

View file

@ -6,7 +6,7 @@ import urllib.request
from html import unescape
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from runtime.tools.base import ToolSpec
_UA = (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "

View file

@ -10,7 +10,7 @@ import urllib.request
from html import unescape
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from runtime.tools.base import ToolSpec
_UA = (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "

View file

@ -3,8 +3,8 @@ from __future__ import annotations
from pathlib import Path
from typing import Any
from oclaw.runtime.tools.base import ToolSpec
from oclaw.runtime.tools.path_guard import resolve_workspace_path
from runtime.tools.base import ToolSpec
from runtime.tools.path_guard import resolve_workspace_path
def write_file_tool() -> ToolSpec: