重构仓库目录为统一的 runtime 分层并清理历史 openclaw 残留。

本次迁移将网关/通道/工具/技能/脚本与协议资源集中到新结构,统一路径常量与脚本转发机制,减少顶层噪音并保证运行与测试行为一致。

Made-with: Cursor
This commit is contained in:
oliver 2026-04-25 01:24:23 +08:00
parent ba3836f00f
commit 4a23b715a2
498 changed files with 2760 additions and 2200 deletions

View file

@ -0,0 +1,50 @@
from __future__ import annotations
from pathlib import Path
from oclaw.platform.config.paths import PROJECT_ROOT
def oclaw_root() -> Path:
return (PROJECT_ROOT / "oclaw").resolve()
def runtime_root() -> Path:
return (oclaw_root() / "runtime").resolve()
def runtime_skills_root() -> Path:
return (runtime_root() / "skills").resolve()
def runtime_hooks_root() -> Path:
return (runtime_root() / "hooks").resolve()
def runtime_hooks_bundled_root() -> Path:
return (runtime_hooks_root() / "bundled").resolve()
def runtime_extensions_root() -> Path:
return (runtime_root() / "extensions").resolve()
def runtime_operations_scripts_root() -> Path:
return (runtime_root() / "operations" / "scripts").resolve()
def ws_protocol_schemas_root() -> Path:
return (oclaw_root() / "interfaces" / "ws" / "protocol_schemas").resolve()
__all__ = [
"oclaw_root",
"runtime_root",
"runtime_skills_root",
"runtime_hooks_root",
"runtime_hooks_bundled_root",
"runtime_extensions_root",
"runtime_operations_scripts_root",
"ws_protocol_schemas_root",
]

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2025 Peter Steinberger (OpenClaw)
Copyright (c) 2025 Peter Steinberger (Oclaw)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -23,5 +23,5 @@ SOFTWARE.
---
The Python modules `tool_call_id.py` and `replay_policy.py` in this directory
implement replay / tool-call-id handling inspired by OpenClaw's
implement replay / tool-call-id handling inspired by Oclaw's
`src/agents/tool-call-id.ts` and `src/agents/transcript-policy.ts`.

View file

@ -37,7 +37,7 @@ def build_default_model() -> ChatModel:
return RuleBasedChatModel()
if mode == "ollama":
try:
from oclaw.agents.factory import DEFAULT_OLLAMA_BASE_URL, DEFAULT_OLLAMA_MODEL
from oclaw.runtime.agents.factory import DEFAULT_OLLAMA_BASE_URL, DEFAULT_OLLAMA_MODEL
return OpenAIChatModel(model=DEFAULT_OLLAMA_MODEL, api_key="ollama", base_url=DEFAULT_OLLAMA_BASE_URL)
except Exception:

View file

@ -1,10 +1,10 @@
"""Transcript replay policy for OpenAI-compatible Chat Completions.
Inspired by OpenClaw (MIT) `src/agents/transcript-policy.ts` defaults for
Inspired by Oclaw (MIT) `src/agents/transcript-policy.ts` defaults for
`openai-completions`: enable strict tool-call-id sanitization so proxies and
multi-provider histories do not break on id format / length.
See OPENCLAW_MIT_LICENSE.txt in this package.
See OCLAW_MIT_LICENSE.txt in this package.
"""
from __future__ import annotations

View file

@ -1,10 +1,10 @@
"""OpenAI-compatible tool_call_id / tool result id rewriting.
Inspired by OpenClaw (MIT) `src/agents/tool-call-id.ts`: sanitize ids to strict
Inspired by Oclaw (MIT) `src/agents/tool-call-id.ts`: sanitize ids to strict
alphanumeric form and keep assistant.tool_calls[].id paired with role=tool
tool_call_id in encounter order.
See OPENCLAW_MIT_LICENSE.txt in this package.
See OCLAW_MIT_LICENSE.txt in this package.
"""
from __future__ import annotations

View file

@ -705,7 +705,7 @@ def penalty_row_status(
def build_tool_wire_snapshot(store: Any, *, role: str | None = None) -> dict[str, Any]:
"""Aggregate MCP install list + usage + policies for Admin GET."""
from oclaw.tools.mcp.registry import McpRegistry
from oclaw.runtime.tools.mcp.registry import McpRegistry
admin = load_merged_admin_config(store)
role_norm = str(role or "").strip().lower() or None

View file

@ -10,7 +10,7 @@ from oclaw.platform.llm.transports.base import ChatModel, LLMResponse, LLMToolCa
class GoogleGeminiChatModel(ChatModel):
"""Native Google Gemini streaming transport (SSE), modeled after OpenClaw's google transport."""
"""Native Google Gemini streaming transport (SSE), modeled after Oclaw's google transport."""
def __init__(self, *, model: str, api_key: str, base_url: str | None = None):
self.model = (model or "").strip() or "gemini-2.5-pro"
@ -34,7 +34,7 @@ class GoogleGeminiChatModel(ChatModel):
{
"name": name,
"description": str(fn.get("description") or ""),
# OpenClaw uses `parametersJsonSchema`
# Oclaw uses `parametersJsonSchema`
"parametersJsonSchema": fn.get("parameters") if isinstance(fn.get("parameters"), dict) else {"type": "object"},
}
)
@ -122,7 +122,7 @@ class GoogleGeminiChatModel(ChatModel):
model_path = self.model
if not model_path.startswith("models/") and not model_path.startswith("tunedModels/"):
model_path = f"models/{model_path}"
# Prefer header auth (OpenClaw-style); avoid forcing key into query string.
# Prefer header auth (Oclaw-style); avoid forcing key into query string.
return f"{base}/{model_path}:streamGenerateContent?alt=sse"
@staticmethod

View file

@ -153,7 +153,7 @@ class OpenAIChatModel(ChatModel):
try:
from oclaw.platform.config.paths import db_path
from oclaw.platform.persistence.sqlite_store import SqliteStore
from oclaw.tools.exposure_plan import build_llm_tools_plan
from oclaw.runtime.tools.exposure_plan import build_llm_tools_plan
plan = build_llm_tools_plan(
store=SqliteStore(db_path()),

View file

@ -125,7 +125,7 @@ class SessionsListMeta:
@dataclass(frozen=True)
class OpenClawTask:
class OclawTask:
id: str
tenant_id: str
session_id: str
@ -143,7 +143,7 @@ class OpenClawTask:
@dataclass(frozen=True)
class OpenClawRun:
class OclawRun:
run_id: str
tenant_id: str
session_id: str
@ -774,7 +774,7 @@ class SqliteStore:
)
conn.execute(
"""
CREATE TABLE IF NOT EXISTS openclaw_task (
CREATE TABLE IF NOT EXISTS oclaw_task (
id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
session_id TEXT NOT NULL,
@ -794,7 +794,7 @@ class SqliteStore:
)
conn.execute(
"""
CREATE TABLE IF NOT EXISTS openclaw_run (
CREATE TABLE IF NOT EXISTS oclaw_run (
run_id TEXT PRIMARY KEY,
tenant_id TEXT NOT NULL,
session_id TEXT NOT NULL,
@ -807,7 +807,7 @@ class SqliteStore:
)
conn.execute(
"""
CREATE TABLE IF NOT EXISTS openclaw_attempt (
CREATE TABLE IF NOT EXISTS oclaw_attempt (
id INTEGER PRIMARY KEY AUTOINCREMENT,
run_id TEXT NOT NULL,
tenant_id TEXT NOT NULL,
@ -821,16 +821,16 @@ class SqliteStore:
"""
)
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_openclaw_task_status_updated ON openclaw_task(status, updated_at)"
"CREATE INDEX IF NOT EXISTS idx_oclaw_task_status_updated ON oclaw_task(status, updated_at)"
)
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_openclaw_task_tenant_session ON openclaw_task(tenant_id, session_id, created_at DESC)"
"CREATE INDEX IF NOT EXISTS idx_oclaw_task_tenant_session ON oclaw_task(tenant_id, session_id, created_at DESC)"
)
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_openclaw_run_tenant_session ON openclaw_run(tenant_id, session_id, updated_at DESC)"
"CREATE INDEX IF NOT EXISTS idx_oclaw_run_tenant_session ON oclaw_run(tenant_id, session_id, updated_at DESC)"
)
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_openclaw_attempt_run_no ON openclaw_attempt(run_id, attempt_no)"
"CREATE INDEX IF NOT EXISTS idx_oclaw_attempt_run_no ON oclaw_attempt(run_id, attempt_no)"
)
conn.execute(
"CREATE INDEX IF NOT EXISTS idx_knowledge_chunk_source_updated ON knowledge_chunk(source, updated_at)"
@ -2685,7 +2685,7 @@ class SqliteStore:
uid = str(user_id or "").strip()
if not uid:
return
from oclaw.agents.specialists import dump_agent_profile_bindings, parse_agent_profile_bindings
from oclaw.runtime.agents.specialists import dump_agent_profile_bindings, parse_agent_profile_bindings
seeded_key = f"llm_personal_pool_seeded:{uid}"
act_key = active_llm_profile_setting_key(uid, username)
@ -4953,22 +4953,22 @@ class SqliteStore:
return int(cur.rowcount or 0)
# ----------------------------
# OpenClaw tasks
# Oclaw tasks
# ----------------------------
def openclaw_task_create(
def oclaw_task_create(
self,
*,
tenant_id: str,
session_id: str,
task_type: str = "async_turn",
payload: dict[str, Any] | None = None,
) -> OpenClawTask:
) -> OclawTask:
tid = str(uuid.uuid4())
ts = utc_now_iso()
with self._connect() as conn:
conn.execute(
"""
INSERT INTO openclaw_task
INSERT INTO oclaw_task
(id, tenant_id, session_id, task_type, status, payload, result, attempt_count, claimed_by, lease_expires_at, last_error, created_at, updated_at, finished_at)
VALUES (?, ?, ?, ?, 'queued', ?, '{}', 0, NULL, NULL, '', ?, ?, NULL)
""",
@ -4982,18 +4982,18 @@ class SqliteStore:
ts,
),
)
got = self.openclaw_task_get(task_id=tid)
got = self.oclaw_task_get(task_id=tid)
if not got:
raise RuntimeError("failed to create openclaw task")
raise RuntimeError("failed to create oclaw task")
return got
def openclaw_task_claim(
def oclaw_task_claim(
self,
*,
worker_id: str,
lease_seconds: int = 90,
task_type: str | None = None,
) -> OpenClawTask | None:
) -> OclawTask | None:
now = datetime.now(timezone.utc)
lease_expires = (now + timedelta(seconds=max(15, min(int(lease_seconds or 90), 1800)))).isoformat()
now_iso = now.isoformat()
@ -5006,7 +5006,7 @@ class SqliteStore:
params.append(tt)
row = conn.execute(
f"""
SELECT id FROM openclaw_task
SELECT id FROM oclaw_task
WHERE {where}
ORDER BY created_at ASC
LIMIT 1
@ -5018,7 +5018,7 @@ class SqliteStore:
task_id = str(row["id"])
cur = conn.execute(
"""
UPDATE openclaw_task
UPDATE oclaw_task
SET status = 'claimed',
attempt_count = attempt_count + 1,
claimed_by = ?,
@ -5031,14 +5031,14 @@ class SqliteStore:
)
if not cur.rowcount:
return None
return self.openclaw_task_get(task_id=task_id)
return self.oclaw_task_get(task_id=task_id)
def openclaw_task_finish(self, *, task_id: str, result: dict[str, Any] | None = None) -> bool:
def oclaw_task_finish(self, *, task_id: str, result: dict[str, Any] | None = None) -> bool:
ts = utc_now_iso()
with self._connect() as conn:
cur = conn.execute(
"""
UPDATE openclaw_task
UPDATE oclaw_task
SET status = 'done',
result = ?,
lease_expires_at = NULL,
@ -5051,12 +5051,12 @@ class SqliteStore:
)
return bool(cur.rowcount and cur.rowcount > 0)
def openclaw_task_fail(self, *, task_id: str, error: str, result: dict[str, Any] | None = None) -> bool:
def oclaw_task_fail(self, *, task_id: str, error: str, result: dict[str, Any] | None = None) -> bool:
ts = utc_now_iso()
with self._connect() as conn:
cur = conn.execute(
"""
UPDATE openclaw_task
UPDATE oclaw_task
SET status = 'failed',
result = ?,
lease_expires_at = NULL,
@ -5069,7 +5069,7 @@ class SqliteStore:
)
return bool(cur.rowcount and cur.rowcount > 0)
def openclaw_task_get(self, *, task_id: str, tenant_id: str | None = None) -> OpenClawTask | None:
def oclaw_task_get(self, *, task_id: str, tenant_id: str | None = None) -> OclawTask | None:
where = "id = ?"
params: list[Any] = [str(task_id)]
if tenant_id:
@ -5079,7 +5079,7 @@ class SqliteStore:
row = conn.execute(
"""
SELECT id, tenant_id, session_id, task_type, status, payload, result, attempt_count, claimed_by, lease_expires_at, last_error, created_at, updated_at, finished_at
FROM openclaw_task
FROM oclaw_task
WHERE """ + where + """
LIMIT 1
""",
@ -5087,7 +5087,7 @@ class SqliteStore:
).fetchone()
if not row:
return None
return OpenClawTask(
return OclawTask(
id=str(row["id"]),
tenant_id=str(row["tenant_id"]),
session_id=str(row["session_id"]),
@ -5104,14 +5104,14 @@ class SqliteStore:
finished_at=str(row["finished_at"]) if row["finished_at"] else None,
)
def openclaw_task_list(
def oclaw_task_list(
self,
*,
status: str | None = None,
limit: int = 50,
tenant_id: str | None = None,
session_id: str | None = None,
) -> list[OpenClawTask]:
) -> list[OclawTask]:
lim = max(1, min(int(limit or 50), 500))
where = ""
params: list[Any] = []
@ -5129,17 +5129,17 @@ class SqliteStore:
rows = conn.execute(
f"""
SELECT id, tenant_id, session_id, task_type, status, payload, result, attempt_count, claimed_by, lease_expires_at, last_error, created_at, updated_at, finished_at
FROM openclaw_task
FROM oclaw_task
{where_clause}
ORDER BY created_at DESC
LIMIT ?
""",
(*params, lim),
).fetchall()
out: list[OpenClawTask] = []
out: list[OclawTask] = []
for row in rows:
out.append(
OpenClawTask(
OclawTask(
id=str(row["id"]),
tenant_id=str(row["tenant_id"]),
session_id=str(row["session_id"]),
@ -5158,7 +5158,7 @@ class SqliteStore:
)
return out
def openclaw_run_upsert(
def oclaw_run_upsert(
self,
*,
run_id: str,
@ -5171,7 +5171,7 @@ class SqliteStore:
with self._connect() as conn:
conn.execute(
"""
INSERT INTO openclaw_run(run_id, tenant_id, session_id, status, payload, created_at, updated_at)
INSERT INTO oclaw_run(run_id, tenant_id, session_id, status, payload, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(run_id) DO UPDATE SET
status = excluded.status,
@ -5190,7 +5190,7 @@ class SqliteStore:
)
return True
def openclaw_attempt_append(
def oclaw_attempt_append(
self,
*,
run_id: str,
@ -5205,7 +5205,7 @@ class SqliteStore:
with self._connect() as conn:
cur = conn.execute(
"""
INSERT INTO openclaw_attempt(run_id, tenant_id, session_id, attempt_no, status, reason, payload, created_at)
INSERT INTO oclaw_attempt(run_id, tenant_id, session_id, attempt_no, status, reason, payload, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""",
(
@ -5221,13 +5221,13 @@ class SqliteStore:
)
return int(cur.lastrowid or 0)
def openclaw_attempt_list(self, *, run_id: str, limit: int = 30) -> list[dict[str, Any]]:
def oclaw_attempt_list(self, *, run_id: str, limit: int = 30) -> list[dict[str, Any]]:
lim = max(1, min(int(limit or 30), 200))
with self._connect() as conn:
rows = conn.execute(
"""
SELECT id, run_id, tenant_id, session_id, attempt_no, status, reason, payload, created_at
FROM openclaw_attempt
FROM oclaw_attempt
WHERE run_id = ?
ORDER BY attempt_no ASC
LIMIT ?
@ -5251,7 +5251,7 @@ class SqliteStore:
)
return out
def openclaw_run_get(self, *, run_id: str, tenant_id: str | None = None) -> OpenClawRun | None:
def oclaw_run_get(self, *, run_id: str, tenant_id: str | None = None) -> OclawRun | None:
where = "run_id = ?"
params: list[Any] = [str(run_id)]
if tenant_id:
@ -5261,7 +5261,7 @@ class SqliteStore:
row = conn.execute(
f"""
SELECT run_id, tenant_id, session_id, status, payload, created_at, updated_at
FROM openclaw_run
FROM oclaw_run
WHERE {where}
LIMIT 1
""",
@ -5269,7 +5269,7 @@ class SqliteStore:
).fetchone()
if not row:
return None
return OpenClawRun(
return OclawRun(
run_id=str(row["run_id"]),
tenant_id=str(row["tenant_id"]),
session_id=str(row["session_id"]),
@ -5279,14 +5279,14 @@ class SqliteStore:
updated_at=str(row["updated_at"]),
)
def openclaw_run_list(
def oclaw_run_list(
self,
*,
tenant_id: str,
session_id: str | None = None,
status: str | None = None,
limit: int = 50,
) -> list[OpenClawRun]:
) -> list[OclawRun]:
lim = max(1, min(int(limit or 50), 300))
where = "tenant_id = ?"
params: list[Any] = [str(tenant_id)]
@ -5300,17 +5300,17 @@ class SqliteStore:
rows = conn.execute(
f"""
SELECT run_id, tenant_id, session_id, status, payload, created_at, updated_at
FROM openclaw_run
FROM oclaw_run
WHERE {where}
ORDER BY updated_at DESC
LIMIT ?
""",
(*params, lim),
).fetchall()
out: list[OpenClawRun] = []
out: list[OclawRun] = []
for row in rows:
out.append(
OpenClawRun(
OclawRun(
run_id=str(row["run_id"]),
tenant_id=str(row["tenant_id"]),
session_id=str(row["session_id"]),