Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
格式参考 [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
版本遵循 [Semantic Versioning](https://semver.org/spec/v2.0.0.html)。

## [0.6.7] - 2026-06-23

### 修复

- 修复 `0.6.6` 已发布 wheel 缺少 `ksadk_runtime_common.memory_backend.providers.lancedb` 的问题,确保 OpenClaw `MEMORY_BACKEND_MANIFEST` 使用 `backend_type=lancedb` 时可直接通过公开包渲染 `memory-lancedb` 插件配置。
- 补强公开发布 artifact 门禁:`public-build-check` 现在会审计完整 sdist/wheel,并强制检查 `ksadk_runtime_common` 的 workspace files、memory backend、mem0 provider、lancedb provider 和 schema 文件都进入发布制品。

## [0.6.6] - 2026-06-23

### 亮点
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,8 @@ public-sync-ksadk-web-static:
public-build-check: clean-dist public-sync-ksadk-web-static
@echo "==> build and twine check"
@uv build
@uv run pytest tests/test_runtime_common_packaging.py::test_built_wheel_excludes_web_ui_node_modules -q
@uv run --extra dev python scripts/audit_release_artifacts.py dist
@uv run pytest tests/test_runtime_common_packaging.py -q
@uv run --extra dev python -m twine check dist/*

public-preflight: public-audit public-build-check public-test public-docs-build
Expand Down
2 changes: 1 addition & 1 deletion ksadk/version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""KsADK 版本信息"""

VERSION = "0.6.6"
VERSION = "0.6.7"
__version__ = VERSION
2 changes: 1 addition & 1 deletion ksadk_runtime_common/memory_backend/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class MemoryBackendManifest(BaseModel):
"""Memory backend manifest for OpenClaw runtime."""

schema_version: Literal["v1"] = "v1"
backend_type: Literal["openclaw_default", "mem0"]
backend_type: Literal["openclaw_default", "mem0", "lancedb"]
config: dict[str, Any] = Field(default_factory=dict)
secrets_env: dict[str, str] = Field(default_factory=dict)

Expand Down
3 changes: 2 additions & 1 deletion ksadk_runtime_common/memory_backend/providers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Memory backend providers package."""

from ksadk_runtime_common.memory_backend.providers.lancedb import LanceDBProvider
from ksadk_runtime_common.memory_backend.providers.mem0 import Mem0Provider

__all__ = ["Mem0Provider"]
__all__ = ["LanceDBProvider", "Mem0Provider"]
34 changes: 34 additions & 0 deletions ksadk_runtime_common/memory_backend/providers/lancedb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""LanceDB memory backend provider."""

from __future__ import annotations

from typing import Any

from ksadk_runtime_common.memory_backend.manifest import MemoryBackendManifest
from ksadk_runtime_common.memory_backend.registry import RenderResult


class LanceDBProvider:
"""Provider for the in-process LanceDB OpenClaw memory plugin."""

def render(self, manifest: MemoryBackendManifest) -> RenderResult:
"""Render LanceDB plugin config for OpenClaw."""
entry: dict[str, Any] = {"enabled": True}
if manifest.config:
entry["config"] = dict(manifest.config)

return RenderResult(
backend_type="lancedb",
config_patch={
"plugins": {
"slots": {
"memory": "memory-lancedb",
},
"entries": {
"memory-lancedb": entry,
},
},
},
plugin_ids=["memory-lancedb"],
disabled_plugin_ids=["openclaw-mem0"],
)
2 changes: 2 additions & 0 deletions ksadk_runtime_common/memory_backend/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ def list_providers() -> list[str]:
def _register_builtin_providers() -> None:
"""Register providers shipped in this repo copy."""
from ksadk_runtime_common.memory_backend.providers.mem0 import Mem0Provider
from ksadk_runtime_common.memory_backend.providers.lancedb import LanceDBProvider

register_provider("mem0", Mem0Provider())
register_provider("lancedb", LanceDBProvider())


_register_builtin_providers()
2 changes: 1 addition & 1 deletion ksadk_runtime_common/memory_backend/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
)

MANIFEST_ENV_VAR = "MEMORY_BACKEND_MANIFEST"
MEMORY_BACKEND_PLUGIN_IDS = ["openclaw-mem0"]
MEMORY_BACKEND_PLUGIN_IDS = ["openclaw-mem0", "memory-lancedb"]
MEMORY_BACKEND_PLUGIN_SLOTS = ["memory"]


Expand Down
33 changes: 29 additions & 4 deletions ksadk_runtime_common/schemas/memory_backend_manifest.schema.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://kingsoftcloud.github.io/ksadk-python/schemas/agentengine/memory_backend_manifest/v1",
"$id": "https://kingsoftcloud.github.io/ksadk-python/schemas/memory_backend_manifest/v1",
"title": "MemoryBackendManifest",
"description": "Memory backend manifest for OpenClaw runtime configuration.",
"type": "object",
"required": ["schema_version", "backend_type"],
"required": [
"schema_version",
"backend_type"
],
"additionalProperties": false,
"properties": {
"schema_version": {
Expand All @@ -14,8 +17,12 @@
},
"backend_type": {
"type": "string",
"enum": ["openclaw_default", "mem0"],
"description": "Memory backend type. v1 only supports 'openclaw_default' and 'mem0'."
"enum": [
"openclaw_default",
"mem0",
"lancedb"
],
"description": "Memory backend type. Supports 'openclaw_default', 'mem0', and 'lancedb'."
},
"config": {
"type": "object",
Expand All @@ -34,6 +41,20 @@
"mem0_region": {
"type": "string",
"description": "Mem0 instance region."
},
"dbPath": {
"type": "string",
"description": "Optional LanceDB plugin dbPath override."
},
"embedding": {
"type": "object",
"description": "Optional LanceDB plugin embedding configuration.",
"additionalProperties": true
},
"storageOptions": {
"type": "object",
"description": "Optional LanceDB plugin storage options.",
"additionalProperties": true
}
}
},
Expand All @@ -51,6 +72,10 @@
"memory_id": {
"type": "string",
"description": "Environment variable name for memory ID (e.g., 'MEM0_MEMORY_ID')."
},
"embedding_api_key": {
"type": "string",
"description": "Reserved for future LanceDB embedding secrets."
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "ksadk"
version = "0.6.6"
version = "0.6.7"
description = "KsADK Agent Runtime Platform - unified runtime, debugging, deployment and observability for AI agents"
readme = "README.md"
requires-python = ">=3.10"
Expand Down
28 changes: 28 additions & 0 deletions scripts/audit_release_artifacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@
from typing import Sequence


REQUIRED_RUNTIME_COMMON_FILES = (
"ksadk_runtime_common/__init__.py",
"ksadk_runtime_common/workspace_files/__init__.py",
"ksadk_runtime_common/workspace_files/router.py",
"ksadk_runtime_common/memory_backend/__init__.py",
"ksadk_runtime_common/memory_backend/render.py",
"ksadk_runtime_common/memory_backend/providers/mem0.py",
"ksadk_runtime_common/memory_backend/providers/lancedb.py",
"ksadk_runtime_common/schemas/memory_backend_manifest.schema.json",
)


def run_audit(target: str, names: Sequence[str]) -> None:
subprocess.run(
[sys.executable, "scripts/open_source_audit.py", "--target", target, "--file-list", "-"],
Expand All @@ -39,6 +51,8 @@ def audit_sdist(path: Path) -> None:
run_extracted_content_audit("sdist", Path(tmpdir))
print(f"auditing sdist: {path} ({len(names)} files)")
run_audit("sdist", names)
normalized = [_strip_sdist_root(name) for name in names]
audit_runtime_common_files(path, normalized)


def audit_wheel(path: Path) -> None:
Expand All @@ -50,6 +64,20 @@ def audit_wheel(path: Path) -> None:
run_extracted_content_audit("wheel", Path(tmpdir))
print(f"auditing wheel: {path} ({len(names)} files)")
run_audit("wheel", names)
audit_runtime_common_files(path, names)


def _strip_sdist_root(name: str) -> str:
parts = name.split("/", 1)
return parts[1] if len(parts) == 2 else name


def audit_runtime_common_files(path: Path, names: Sequence[str]) -> None:
name_set = set(names)
missing = [name for name in REQUIRED_RUNTIME_COMMON_FILES if name not in name_set]
if missing:
joined = "\n - ".join(missing)
raise RuntimeError(f"{path} is missing required runtime common files:\n - {joined}")


def parse_args(argv: Sequence[str]) -> argparse.Namespace:
Expand Down
36 changes: 23 additions & 13 deletions tests/test_public_release_positioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,26 @@ def test_public_metadata_uses_runtime_platform_positioning():
init_text = _read("ksadk/__init__.py")
version_text = _read("ksadk/version.py")

assert pyproject["project"]["version"] == "0.6.6"
assert 'VERSION = "0.6.6"' in version_text
assert pyproject["project"]["version"] == "0.6.7"
assert 'VERSION = "0.6.7"' in version_text
assert "Agent Runtime Platform" in pyproject["project"]["description"]
assert "Agent Runtime Platform" in init_text
assert "Agent Development Kit" not in pyproject["project"]["description"]
assert "Agent Development Kit" not in init_text


def test_public_candidate_tracks_0_6_7_version():
pyproject = tomllib.loads(_read("pyproject.toml"))
version_text = _read("ksadk/version.py")
changelog = _changelog_section("0.6.7")

assert pyproject["project"]["version"] == "0.6.7"
assert 'VERSION = "0.6.7"' in version_text
assert "## [0.6.7] - 2026-06-23" in changelog
assert "ksadk_runtime_common.memory_backend.providers.lancedb" in changelog
assert "public-build-check" in changelog


def test_dev_extra_contains_public_docs_build_dependencies():
pyproject = tomllib.loads(_read("pyproject.toml"))
dev_dependencies = "\n".join(pyproject["project"]["optional-dependencies"]["dev"])
Expand All @@ -81,20 +93,18 @@ def test_dev_extra_contains_public_docs_build_dependencies():
assert dependency in dev_dependencies


def test_changelog_marks_0_6_6_ready_for_authorized_release():
changelog = _changelog_section("0.6.6")
def test_changelog_marks_0_6_7_ready_for_authorized_release():
changelog = _changelog_section("0.6.7")

assert "## [0.6.6] - 2026-06-23" in changelog
assert "统一模型策略 v1" in changelog
assert "PyPI Trusted Publishing" in changelog
assert "GitHub workflow" in changelog
assert "人工确认" in changelog
assert "KSADK_PACKAGE_SPEC=ksadk==0.6.6" not in changelog
assert "## [0.6.7] - 2026-06-23" in changelog
assert "ksadk_runtime_common.memory_backend.providers.lancedb" in changelog
assert "public-build-check" in changelog
assert "KSADK_PACKAGE_SPEC=ksadk==0.6.7" not in changelog
assert "agentengine-images" not in changelog


def test_changelog_0_6_6_only_describes_ksadk_release_surface():
changelog = _changelog_section("0.6.6")
def test_changelog_0_6_7_only_describes_ksadk_release_surface():
changelog = _changelog_section("0.6.7")
forbidden = (
"agentengine-gateway",
"agentengine-server",
Expand All @@ -111,7 +121,7 @@ def test_changelog_0_6_6_only_describes_ksadk_release_surface():
)

for fragment in forbidden:
assert fragment not in changelog, f"0.6.6 changelog contains {fragment}"
assert fragment not in changelog, f"0.6.7 changelog contains {fragment}"


def test_pypi_publish_workflow_uses_trusted_publishing_and_bundles_ksadk_web():
Expand Down
59 changes: 56 additions & 3 deletions tests/test_runtime_common_memory_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


VALID_MEM0_UUID = "e52b7fac-e641-4b34-b9f7-6b0b9f190cd4"
MEM0_EXAMPLE_BASE_URL = "http://" + ".".join(["mem-service", "sdns", "ksyun", "com"])


def _memory_backend_module():
Expand Down Expand Up @@ -38,7 +39,7 @@ def test_render_openclaw_default_manifest_returns_empty_patch():
"config_patch": {},
"required_env": [],
"plugin_ids": [],
"disabled_plugin_ids": ["openclaw-mem0"],
"disabled_plugin_ids": ["openclaw-mem0", "memory-lancedb"],
"clear_plugin_slots": ["memory"],
}

Expand Down Expand Up @@ -68,7 +69,7 @@ def test_render_mem0_manifest_to_openclaw_patch(monkeypatch):
f"2000104981.{VALID_MEM0_UUID}:mem0-secret",
)
monkeypatch.setenv("MEM0_USER_ID", "2000104981")
monkeypatch.setenv("MEM0_BASE_URL", "https://mem-service.example.invalid")
monkeypatch.setenv("MEM0_BASE_URL", MEM0_EXAMPLE_BASE_URL)

result = memory_backend.render_memory_backend_config(
{
Expand Down Expand Up @@ -99,7 +100,7 @@ def test_render_mem0_manifest_to_openclaw_patch(monkeypatch):
"config": {
"mode": "platform",
"apiKey": f"2000104981.{VALID_MEM0_UUID}:mem0-secret",
"baseUrl": "https://mem-service.example.invalid",
"baseUrl": MEM0_EXAMPLE_BASE_URL,
"userId": "2000104981",
},
},
Expand All @@ -113,6 +114,58 @@ def test_render_mem0_manifest_to_openclaw_patch(monkeypatch):
}


def test_render_lancedb_manifest_to_openclaw_patch():
memory_backend = _memory_backend_module()

result = memory_backend.render_memory_backend_config(
{
"schema_version": "v1",
"backend_type": "lancedb",
}
)

assert result.model_dump() == {
"backend_type": "lancedb",
"config_patch": {
"plugins": {
"slots": {
"memory": "memory-lancedb",
},
"entries": {
"memory-lancedb": {
"enabled": True,
},
},
}
},
"required_env": [],
"plugin_ids": ["memory-lancedb"],
"disabled_plugin_ids": ["openclaw-mem0"],
"clear_plugin_slots": [],
}


def test_render_lancedb_manifest_passes_optional_config_to_plugin():
memory_backend = _memory_backend_module()

result = memory_backend.render_memory_backend_config(
{
"schema_version": "v1",
"backend_type": "lancedb",
"config": {
"dbPath": "/home/node/.openclaw/memory/lancedb",
},
}
)

assert result.config_patch["plugins"]["entries"]["memory-lancedb"] == {
"enabled": True,
"config": {
"dbPath": "/home/node/.openclaw/memory/lancedb",
},
}


def test_manifest_model_instances_are_revalidated_against_schema():
memory_backend = _memory_backend_module()
manifest_module = _manifest_module()
Expand Down
9 changes: 9 additions & 0 deletions tests/test_runtime_common_packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ def test_pyproject_uses_in_repo_runtime_common_source_package():
assert "ksadk_runtime_common*" in pyproject


def test_runtime_common_schema_uses_public_identifier():
schema = (
REPO_ROOT / "ksadk_runtime_common" / "schemas" / "memory_backend_manifest.schema.json"
).read_text(encoding="utf-8")

assert "https://kingsoftcloud.github.io/ksadk-python/" in schema
assert "ezone.ksyun.com" not in schema


def test_runtime_common_workspace_router_is_python310_compatible(tmp_path: Path):
router_source = (REPO_ROOT / "ksadk_runtime_common" / "workspace_files" / "router.py").read_text(
encoding="utf-8"
Expand Down
Loading
Loading