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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
102 changes: 101 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
test:
runs-on: ubuntu-latest
env:
KSADK_WEB_VERSION: "0.2.19"
KSADK_WEB_VERSION: "0.3.0"
steps:
- uses: actions/checkout@v4

Expand Down Expand Up @@ -59,3 +59,103 @@ jobs:

- name: Audit wheel and sdist file lists
run: make open-source-audit-dist

# goal-00: google-adk 多版本 matrix。依赖窗口 >=1.34.0,<3.0,
# 对最低锚点 1.34.x 与最新 2.x(2.5.x)各跑一遍全量测试,防止任何一端回归。
# 版本差异统一由 ksadk/compat/adk_compat.py 收口(见 docs/adk-multi-version-compat.md)。
test-adk-matrix:
name: full pytest (google-adk ${{ matrix.google-adk }})
runs-on: ubuntu-latest
env:
KSADK_WEB_VERSION: "0.3.0"
strategy:
fail-fast: false
matrix:
google-adk: ["1.34.3", "2.5.0"]
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install dependencies
run: uv sync --extra all

- name: Pin google-adk for this matrix leg
run: uv pip install "google-adk==${{ matrix.google-adk }}"

- name: Verify google-adk version
run: uv run --no-sync python -c "from importlib.metadata import version; print('google-adk', version('google-adk'))"

# Static web assets are deliberately not tracked in the Python source
# tree; fetch and verify the released npm payload before wheel build.
- name: Sync KsADK Web static assets
run: make public-sync-ksadk-web-static

# Packaging tests inspect the wheel itself; build it in each isolated ADK
# environment rather than depending on an artifact from another job.
- name: Build package artifacts
run: uv build

# --no-sync: 防止 uv run 按 lock 重新同步、把上一步行覆盖的 adk 版本回退。
- name: Run full test suite
run: uv run --no-sync pytest tests/ -q

# goal-16: Windows a2a 命令 bug 回归(用户首报:"No such command 'a2a'")。
# 在本机 macOS 无法闭环 Windows,故 CI 加 Windows runner 跑 CLI smoke:
# `agentengine a2a -h` 退出码 0,且 a2a 命令确已注册(非 try/except ImportError 静默吞)。
test-cli-windows:
name: CLI smoke (windows-latest, a2a -h 注册回归)
runs-on: windows-latest
env:
# GitHub's non-interactive Windows output can default to cp1252 while
# KsADK's public CLI help includes Chinese text.
PYTHONUTF8: "1"
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install dependencies
run: uv sync --extra all

- name: a2a -h exits 0
run: uv run --no-sync agentengine a2a -h

- name: a2a command is registered (no silent ImportError swallow)
run: uv run --no-sync python -c "from ksadk.cli import _register_commands, cli; _register_commands(); assert 'a2a' in cli.commands, 'a2a command was silently swallowed'; print('a2a registered OK')"

test-codex-native-runtime:
name: Codex native ManagedRuntime (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install KsADK and native Codex runtime
run: uv sync --extra dev --extra codex

- name: Import platform package, resolve binary, and start local Web
run: uv run --no-sync pytest tests/test_managed_runtime_native_smoke.py -q
4 changes: 2 additions & 2 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
ksadk_web_version:
description: KsADK Web npm version to bundle
required: false
default: "0.2.19"
default: "0.3.0"
approved_source_commit:
description: Reviewed source commit SHA recorded in docs/maintainer-approval-record.md
required: false
Expand Down Expand Up @@ -37,7 +37,7 @@ jobs:
environment:
name: pypi
env:
KSADK_WEB_VERSION: ${{ github.event.inputs.ksadk_web_version || '0.2.19' }}
KSADK_WEB_VERSION: ${{ github.event.inputs.ksadk_web_version || '0.3.0' }}
KSADK_APPROVED_SOURCE_COMMIT: ${{ github.event.inputs.approved_source_commit || vars.KSADK_APPROVED_SOURCE_COMMIT }}
PUBLISH_TARGET: ${{ github.event.inputs.publish_target || 'full' }}
permissions:
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/release-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ on:
paths:
- "pyproject.toml"
- "MANIFEST.in"
- "Makefile"
- "ksadk/**"
- "ksadk_runtime_common/**"
- "scripts/open_source_audit.py"
- "scripts/verify_ksadk_web_static.py"
- ".github/workflows/release-check.yml"

jobs:
Expand All @@ -25,9 +27,19 @@ jobs:
with:
python-version: "3.11"

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: "22"

- name: Install dependencies
run: uv sync --extra dev

- name: Sync pinned KsADK Web static assets
env:
KSADK_WEB_VERSION: "0.3.0"
run: make public-sync-ksadk-web-static

- name: Build artifacts
run: uv build

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,4 @@ site/

# Legacy local UI source is owned by kingsoftcloud/ksadk-web.
ksadk/server/web-ui/
e2e-codex-agent/
12 changes: 12 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ paths = [
'''tests/test_cmd_hermes\.py''',
]

# Route-manifest fixture checksums are deterministic SHA-256 test data, not
# credentials. The public CI scans every public branch's history, including the
# superseded runtime-foundation candidate where this fixture originated.
[[allowlists]]
description = "Allowlist deterministic route-manifest SHA-256 test fixture"
regexes = [
'''ac9086d1592d69d7eecd4260c2ca4bfa06b0daaed5cdf0653c4eb409204ed84d''',
]
paths = [
'''tests/server/test_route_manifest_parity\.py''',
]

# ---- 历史已删文档中的 OPENAI_API_KEY (疑似真 kspmas key) ----
# !!! 安全前置条件 !!!
# 启用本 allowlist 之前, 必须先在金山云 kspmas 控制台 rotate (吊销并重发) 该 key,
Expand Down
38 changes: 38 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,44 @@

## [Unreleased]

## [0.8.0] - 2026-07-24

> **Review candidate, not a published release.** This section covers the work
> merged after `0.7.0` on 2026-07-15. It does not assert that a PyPI/npm
> package, tag, or GitHub Release exists.

### 亮点

- **统一 Runtime 基座**:冻结 `RuntimeEvent v1` 信封和六动词 `RuntimeAdapter`,补齐事件存储、按会话事件序号(`seq_id`)续订的订阅、共享 parser 与历史回放。ADK、LangGraph、A2A、Harness 和 Codex 新集成均以这一契约交换运行状态,而不是各自定义一套 SSE 语义。
- **Hosted UI 进入 AG-UI + A2UI 轨道**:在不改变 OpenAI Responses 既有请求/响应语义的前提下,增加 capability 协商后的 AG-UI transport 和 A2UI activity 投影;无法协商时仍走 Responses fallback。
- **可诊断的会话连续性**:runtime storage 成为会话状态的权威来源,补全结构化 Responses 历史投影、请求 metadata 透传、run 订阅心跳与 idle SSE 保活,刷新、续订、审批和恢复都能基于已持久化事件排查。
- **可组合的运行形态**:加入 A2A wire 1.0 runtime、HarnessApp、CodexRuntime 和 Skill Space 路由;这些能力均保留本地/契约测试,生产环境互操作和真实凭证仍需按部署环境验收。

### 新增

- **事件与 adapter**:新增 RuntimeEvent schema、严格反序列化校验、RuntimeEventStore、session 级订阅、共享 projection/replay parser,以及 ADK/LangGraph 的 adapter contract tests。未知事件不能绕过事件边界进入 replay。
- **AG-UI 与 A2UI**:新增 AG-UI route group、RuntimeEvent 到 activity 的投影、A2UI core/renderer/fixture viewer 和可持久化 action 记录。审批不是另一套 UI 协议,而是事件流中的受控交互状态。
- **A2A**:新增 Agent Card、Protocol Runtime、PostgreSQL TaskStore、account + runtime 复合 owner identity、Task cancel/resume adapter、Space 内动态发现、credential provider、egress policy 与 A2A event adapter。AgentEngine 的托管 composition root 使用 Gateway 验证的五元目标绑定和受信 Card probe;它将 resume state 留在 Runtime 本地 durable storage,并为 `external_public` 提供 HTTPS-only、DNS/IP pin、禁代理、拒绝 3xx 的 NAT transport。app factory 直接装配 A2A 数据面路由;`external_vpc` 仍需单独的 VPC dialer。
- **Harness 与 Codex**:新增声明式 HarnessApp composition root,模型/MCP/tool 配置校验和默认只读 sandbox policy;新增基于官方 app-server transport 的 CodexRuntime、生命周期 phase 映射及离线/显式 live 演示。真实 provider 凭证 E2E 不包含在本候选的发布结论中。
- **框架与 App Factory**:新增 ADK `1.34.x`/`2.x` 兼容层及 CI matrix;server 创建改为 per-app factory/state,路由按职责拆组,WebSocket 也在请求上下文中运行。
- **CLI 与诊断**:新增 `agentengine a2a` 和 `ksadk replay <session-id>`。`replay` 只读取已持久化的 RuntimeEvent,按 `--after-seq-id` / `--before-seq-id` 定位窗口并输出 text 或 JSON transcript;它不重跑模型、工具或副作用,旧式 SessionEvent 也不在此命令的回放范围内。
- **Skills、工具与可观测性**:新增按 `space_id` 定向的 Skill Space 消费路径,并完成 tools、memory、sandbox 和 tracing adapter 的迁移,以便 Harness/runner 在同一运行边界消费它们。

### 修复与性能

- 修复 local/hosted session history 的投影和 metadata 边界,避免刷新后漏失正文、reasoning、tool、approval 或附件状态;恢复请求会先落盘 `resuming` 状态,避免 SSE 返回与持久化状态竞态。
- 修复 run-event 订阅缺少心跳、空闲 SSE 被中间网络断开、MCP API/delete error 行为漂移、Windows ADK 安装与 create-agent streaming 兼容问题。
- 修复 E2B sandbox 执行硬化、workspace 编辑工具选择、Hermes 项目创建,以及 PostgreSQL/in-memory session 后端的连续性与 fail-open 行为。
- 为 agent-scoped session/event 查询增加 covering indexes,降低多会话历史和回放场景下的数据库扫描成本。
- 托管 A2A 在 public-egress 最终投影缺失时按关闭处理;不把 Runtime reasoning、checkpoint handle 或 resume target 写入公开 A2A Task/Message metadata,取消成功后清除 Runtime-local resume state。

### 兼容性、迁移与评审边界

- OpenAI Responses 和 Chat Completions 兼容入口仍是默认基线。AG-UI/A2UI 是可选 Hosted UI 能力,不会要求现有 Responses 客户端改协议。
- 旧版 LangChain 连续性 / HITL 路径不再是 `0.8` 的兼容性承诺。新接入应使用 LangGraph、ADK 或 `RuntimeAdapter`;迁移时先验证 checkpoint、interrupt 和工具语义。
- 本候选的 Python 版本为 `0.8.0`,配套 Web 候选为 `@kingsoftcloud/ksadk-web@0.3.0`。Python release workflow 已固定请求该版本,并逐文件校验 npm tarball 的 `dist-ksadk`、同步目录和 wheel 内静态资源;在 Web `0.3.0` 经受保护 npm 流程发布前,公开 Python 发布会保持阻塞,不会回退到旧版本。
- 公开发布仍被 review/sign-off、clean-export/public preflight、真实 staging evidence 与可选的 Codex provider E2E 阻塞;本条目不构成发布批准。

## [0.7.0] - 2026-07-15

### 亮点
Expand Down
51 changes: 38 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# AgentEngine Makefile
# 用于同步 KsADK Web static 和管理项目

.PHONY: help install clean clean-cache clean-dist clean-static clean-offline dev test publish publish-test public-status public-init-worktree public-worktree-status public-sync-check public-secret-audit public-audit public-version-gate docs-site-build docs-site-dev public-test public-build-check public-build-alias-check public-preflight public-publish-check public-release-approval-check public-publish-gate public-release-tag public-review public-sync-ksadk-web-static open-source-audit-dist open-source-audit-alias-dist openclaw-build openclaw-push openclaw-size hermes-build hermes-push hermes-size sync-ksadk-web-static sync-hosted-ui build-frontend build-webui sync-static webui build-wheel build-all clean-frontend
.PHONY: help install clean clean-cache clean-dist clean-static clean-offline dev test publish publish-test public-status public-init-worktree public-worktree-status public-sync-check public-secret-audit public-audit public-version-gate docs-site-build docs-site-dev public-test public-build-check public-build-alias-check public-preflight public-publish-check public-release-approval-check public-publish-gate public-release-tag public-review public-sync-ksadk-web-static open-source-audit-dist open-source-audit-alias-dist openclaw-build openclaw-push openclaw-size hermes-build hermes-push hermes-size sync-ksadk-web-static verify-ksadk-web-static verify-ksadk-web-wheel-static sync-hosted-ui build-frontend build-webui sync-static webui build-wheel build-all clean-frontend

# 默认目标
help:
Expand All @@ -14,7 +14,7 @@ help:
@echo " make test 运行测试"
@echo ""
@echo " \033[1;32mWeb UI 构建:\033[0m"
@echo " make sync-ksadk-web-static KSADK_WEB_VERSION=latest"
@echo " make sync-ksadk-web-static KSADK_WEB_VERSION=0.3.0"
@echo " 从 @kingsoftcloud/ksadk-web npm 包同步 static"
@echo " make build-frontend 同步 ksadk-web static"
@echo ""
Expand Down Expand Up @@ -267,7 +267,7 @@ PUBLIC_DOCS_URL ?= https://kingsoftcloud.github.io/ksadk-python/
PUBLIC_PYPI_PROJECT ?= ksadk
PUBLIC_ALIAS_PYPI_PROJECT ?= agentengine-sdk-python
PUBLIC_RELEASE_TAG ?= v$(V)
PUBLIC_TEST_TARGETS ?= tests/test_public_release_positioning.py tests/test_config_env_registry.py
PUBLIC_TEST_TARGETS ?= tests/test_public_release_positioning.py tests/test_config_env_registry.py tests/test_managed_runtime_builder.py tests/test_managed_runtime_resolution.py tests/cli/test_cmd_create_codex.py tests/runners/test_codex_runner.py

public-status:
@echo "==> internal worktree"
Expand Down Expand Up @@ -329,20 +329,24 @@ public-sync-check:

public-secret-audit:
@echo "==> secret and sensitive-file audit"
@if git ls-files | grep -E '(^|/)(\.pypirc|kubeconfig|.*\.kubeconfig|id_rsa|id_ed25519)$$'; then \
echo "❌ 发现禁止跟踪的敏感文件"; \
exit 1; \
@if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then \
if git ls-files | grep -E '(^|/)(\.pypirc|kubeconfig|.*\.kubeconfig|id_rsa|id_ed25519)$$'; then \
echo "❌ 发现禁止跟踪的敏感文件"; \
exit 1; \
fi; \
fi
@python3 scripts/public_secret_audit.py
@echo "✅ secret audit passed"

public-audit: public-secret-audit
@echo "==> public source audit"
@blocked=$$(git ls-files | grep -E '^(\.pypirc$$|\.zread/(wiki|site)/)' || true); \
if [ -n "$$blocked" ]; then \
echo "❌ blocked tracked paths:"; \
echo "$$blocked"; \
exit 1; \
@if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then \
blocked=$$(git ls-files | grep -E '^(\.pypirc$$|\.zread/(wiki|site)/)' || true); \
if [ -n "$$blocked" ]; then \
echo "❌ blocked tracked paths:"; \
echo "$$blocked"; \
exit 1; \
fi; \
fi
@python3 scripts/open_source_audit.py --target public-repo
@echo "✅ public path audit passed"
Expand Down Expand Up @@ -373,6 +377,7 @@ public-sync-ksadk-web-static: sync-ksadk-web-static
public-build-check: clean-dist sync-ksadk-web-static
@echo "==> build and twine check"
@uv build
@$(MAKE) verify-ksadk-web-wheel-static
@uv run pytest tests/test_runtime_common_packaging.py -q
@uv run --extra dev python -m twine check dist/*
@$(MAKE) open-source-audit-dist
Expand Down Expand Up @@ -558,7 +563,10 @@ openclaw-build openclaw-push openclaw-size hermes-build hermes-push hermes-size:
# ============================================================

STATIC_DIR := ksadk/server/static
KSADK_WEB_VERSION ?= latest
# The wheel must embed a published, reproducible Web bundle. 0.8.0 is coupled
# to the 0.3.0 Web release; the release job must fail rather than silently
# substituting an older npm package when that release is not visible yet.
KSADK_WEB_VERSION ?= 0.3.0
KSADK_WEB_PACKAGE ?= @kingsoftcloud/ksadk-web
KSADK_WEB_TARBALL_NAME := kingsoftcloud-ksadk-web-$(patsubst v%,%,$(KSADK_WEB_VERSION)).tgz
KSADK_WEB_RELEASE_URL ?=
Expand All @@ -569,7 +577,10 @@ sync-ksadk-web-static:
@echo "Sync KsADK Web static assets from $(KSADK_WEB_PACKAGE)@$(KSADK_WEB_VERSION)"
@rm -rf "$(KSADK_WEB_CACHE_DIR)/package"
@mkdir -p "$(KSADK_WEB_CACHE_DIR)" "$(STATIC_DIR)"
@if [ -n "$(KSADK_WEB_RELEASE_URL)" ]; then \
@if [ -f "$(KSADK_WEB_CACHE_DIR)/$(KSADK_WEB_TARBALL_NAME)" ]; then \
echo "Using cached tarball $(KSADK_WEB_TARBALL_NAME)"; \
echo "$(KSADK_WEB_TARBALL_NAME)" > "$(KSADK_WEB_CACHE_DIR)/.tarball-name"; \
elif [ -n "$(KSADK_WEB_RELEASE_URL)" ]; then \
echo "Using explicit KSADK_WEB_RELEASE_URL=$(KSADK_WEB_RELEASE_URL)"; \
curl -fL --retry 3 --retry-delay 2 --retry-all-errors "$(KSADK_WEB_RELEASE_URL)" -o "$(KSADK_WEB_CACHE_DIR)/$(KSADK_WEB_TARBALL_NAME)"; \
echo "$(KSADK_WEB_TARBALL_NAME)" > "$(KSADK_WEB_CACHE_DIR)/.tarball-name"; \
Expand All @@ -592,8 +603,22 @@ sync-ksadk-web-static:
@rm -rf "$(STATIC_DIR)"
@mkdir -p "$(STATIC_DIR)"
cp -R "$(KSADK_WEB_CACHE_DIR)/package/dist-ksadk/." "$(STATIC_DIR)/"
@$(MAKE) verify-ksadk-web-static
@echo "Synced KsADK Web $(KSADK_WEB_VERSION) static assets into $(STATIC_DIR)"

verify-ksadk-web-static:
@python3 scripts/verify_ksadk_web_static.py \
--expected "$(KSADK_WEB_CACHE_DIR)/package/dist-ksadk" \
--actual "$(STATIC_DIR)" \
--package-root "$(KSADK_WEB_CACHE_DIR)/package" \
--expected-version "$(patsubst v%,%,$(KSADK_WEB_VERSION))"

verify-ksadk-web-wheel-static:
@python3 scripts/verify_ksadk_web_static.py \
--expected "$(KSADK_WEB_CACHE_DIR)/package/dist-ksadk" \
--wheel "$$(ls dist/ksadk-*.whl)" \
--expected-version "$(patsubst v%,%,$(KSADK_WEB_VERSION))"

sync-hosted-ui: sync-ksadk-web-static
@echo "sync-hosted-ui is deprecated; static assets now come from $(KSADK_WEB_PACKAGE)."

Expand Down
Loading
Loading