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
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,52 @@
格式参考 [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
版本遵循 [Semantic Versioning](https://semver.org/spec/v2.0.0.html)。

## [Unreleased]

## [0.7.0] - 2026-07-15

### 亮点

- **Google ADK 长任务支持 invocation 级断点恢复**:KsADK 记录 ADK invocation 映射和最新工具/Agent 状态恢复点,通过共享 PostgreSQL session backend 支持 Pod 重建后继续同一个 run;控制台可按 runtime capability、checkpoint preview 和恢复风险决定是否展示恢复入口。
- **交互终端改为内容优先的 inline TUI**:`agentengine run` / `invoke` 的聊天界面不再占用 alternate screen,保留终端原生 scrollback;流式文本、工具调用和工具结果按实际到达顺序展示,并支持 `/tools` 折叠或展开工具详情。
- **PostgreSQL 会话故障不阻断 Agent**:配置 PostgreSQL 时,驱动缺失、连接或写入异常会进入进程内存降级态并记录结构化告警;驱动补齐或后台探活恢复后,新会话和后续事件自动恢复写入 PostgreSQL。
- **会话事件更易排查**:新增 `ksadk_session_events_readable` PostgreSQL 视图,将原始事件拍平为消息角色、文本、工具名称、生命周期状态和时间等字段。
- **usage 与可观测数据更准确**:LangGraph 流式 usage 会去重、聚合并优先作为当前轮权威值;Langfuse trace 保留 KsADK 已计算的 usage,避免 exporter 二次推断覆盖正确结果。

### 新增

- ADK Runner 接入 `ResumabilityConfig`、`invocation_id` 映射、递增 checkpoint、恢复审计和 runtime capability 描述;新增 `KSADK_ADK_RESUMABLE` 显式开关。
- TUI 新增 `/tools` 命令、模型选择、输入排队、处理中耗时状态、终端背景自适应和 `/clear` 原生 scrollback 清理。
- 新增 PostgreSQL 会话故障恢复 E2E 校验脚本,覆盖 LangGraph、LangChain、ADK、可读视图以及数据库中断后恢复写入。

### 变更

- ADK checkpoint 只在共享 database session backend 下声明可跨 Pod 恢复;in-memory、local 和 SQLite backend 保留审计信息但不点亮恢复入口。Runtime bootstrap 的 Stop/Resume/checkpoint 字段改为跟随 runner 实际能力。
- 新建 Agent、Hermes、OpenClaw 和 MCP 部署时默认开启公网访问;更新已有资源时,未显式传入网络选项则不覆盖服务端现有配置,仍可通过 `--disable-public-access` 明确关闭。
- `agentengine invoke --message` 默认创建新 session,只有显式传入 session 时才复用,避免多次单次调用意外共享上下文。
- 模型上下文窗口区分 provider 返回的原始上限与扣除系统预留后的有效上限,避免 UI 展示值和运行时裁剪阈值混用。
- reasoning delta 仍实时流式返回,但每轮聚合为一条 `reasoning` 事件持久化,减少 PostgreSQL 写放大。
- 降级期间未写入 PostgreSQL 的旧事件不会自动补写;Pod 重启、迁移或请求切换到其他 Pod 时,历史上下文可能不完整,但当前 Agent 请求继续执行。
- PostgreSQL 连接池操作和关闭增加超时边界,避免数据库网络异常拖住请求或 Pod 退出。
- PostgreSQL session 创建改为数据库级幂等,多个 Pod 并发恢复或创建同一 session 时不会因唯一键竞争误触发降级。
- 公开发布流程统一为内部 `master` 经 clean export 生成公开候选,再通过 GitHub PR、Trusted Publishing 发布主包和兼容别名包;移除旧文档部署路径并补齐导出审计边界。

### 修复

- 修复 ADK 恢复能力关闭时被空消息静默转换为新任务、并发 invocation 映射串线、checkpoint ID 重启碰撞、零事件恢复异常和重复审计的问题。
- 修复 ADK LiteLLM 非法工具参数补丁返回错误响应类型及重复包装,并补齐 MCP 结果补丁的幂等保护。
- 修复 inline TUI 中工具调用完成后被统一移动到回复末尾、历史重绘影响原生滚动、浅色终端输入区域不清晰等问题。
- 修复 Remote Runner 的 chat stream 将文本 delta 放在顶层时无法解析,导致远程回复内容缺失的问题。
- 修复 LangGraph 流式 usage chunk 重复、缺少 run id 或与最终事件并存时可能重复累计或丢失的问题。
- 修复 Langfuse exporter 覆盖 KsADK 权威 usage,导致 trace 中 token 数据与运行时不一致的问题。
- 修复 PostgreSQL 恢复后,降级期间创建的 session 无法继续写入 PG 的问题。
- 修复 ADK session 在健康 PostgreSQL 下不刷新其他副本新增事件的问题。
- 修复 DeepAgents 测试 fake model 对空内容 tool call 不产生 stream chunk 的兼容问题。
- 修复 `langchain.agents.create_agent()` 返回 message-state 时,LangChain Runner 丢弃流式文本、思考过程和工具调用/结果并回退为同步执行的问题。
- 修复 Windows Python 3.13 安装 ADK extra 时可能从源码构建 LiteLLM 并因缺少 MSVC linker 失败的问题;显式使用 `LiteLlm` 的用户可先安装官方二进制 wheel。
- 修复 coding profile 未直接暴露 workspace 写文件工具,导致新建文件绕行 dispatcher;同时明确 read/edit 必须串行并让无效编辑参数优先返回准确诊断。
- 修复本地 `agentengine web` 缺少 `ListSessionMessages` action,导致刷新或切换 session 后历史消息无法回显的问题;历史投影保留正文、思考、工具、审批和附件信息。

## [0.6.9] - 2026-07-07

### 亮点
Expand Down
4 changes: 4 additions & 0 deletions docs-site/content/docs/framework/tutorials/adk-agent.en.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ source .venv/bin/activate
pip install -U "ksadk[adk]"
```

<Callout type="warning" title="LiteLlm on Windows Python 3.13">
On Windows Python 3.13, `ksadk[adk]` does not install LiteLLM automatically. This avoids accidental source builds from a mirror or cache that require a local MSVC/Rust toolchain. If your agent explicitly uses `google.adk.models.lite_llm.LiteLlm`, install the official wheel first: `python -m pip install --only-binary=litellm litellm`.
</Callout>

Create `agentengine.yaml`:

```yaml
Expand Down
4 changes: 4 additions & 0 deletions docs-site/content/docs/framework/tutorials/adk-agent.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ source .venv/bin/activate
pip install -U "ksadk[adk]"
```

<Callout type="warning" title="Windows Python 3.13 使用 LiteLlm">
Windows Python 3.13 不会由 `ksadk[adk]` 自动安装 LiteLLM,避免镜像或缓存误选源码包后要求本机具备 MSVC/Rust 构建链。若 Agent 显式使用 `google.adk.models.lite_llm.LiteLlm`,请先安装官方 wheel:`python -m pip install --only-binary=litellm litellm`。
</Callout>

创建 `agentengine.yaml`:

```yaml
Expand Down
37 changes: 37 additions & 0 deletions docs-site/content/docs/references/runtime-sessions-files.en.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,43 @@ Older local clients may use `session_id`:
Use one style consistently. If both are present and disagree, the local runtime
rejects the request.

When PostgreSQL is configured, it is a durable session replica rather than an
availability prerequisite for agent execution. If a connection or write fails,
the runtime continues with its in-process live session and emits a structured
error when it enters `session_backend_state=degraded`. The runtime periodically
probes PostgreSQL; after recovery, new sessions and subsequent events are written
to PostgreSQL again and `session_backend_state=recovered` is logged. Older events
missed during the outage are not backfilled automatically and are not guaranteed
to survive a pod restart or relocation. While PostgreSQL is unavailable, only
history already loaded by the current process is available. A request routed to
another pod may have reduced context, but the current agent request still runs.

### Readable PostgreSQL View

KsADK creates `ksadk_session_events_readable` alongside the raw PostgreSQL
tables. The raw `content_json` and `metadata_json` values remain available, while
the view exposes flattened `message_role`, `message_text`, `tool_name`,
`lifecycle_status`, and `created_at` columns for operators:

```sql
SELECT
session_id,
seq_id,
message_role,
event_type,
message_text,
tool_name,
lifecycle_status,
created_at
FROM ksadk_session_events_readable
WHERE namespace = 'default' AND session_id = '<session-id>'
ORDER BY seq_id;
```

Reasoning deltas are still streamed to clients in real time, but they are
persisted as one aggregated `reasoning` event per turn. Lifecycle events remain
separate and can be inspected through `lifecycle_status`.

### Account Boundary

Hosted deployments pass `account_id` through the request chain. It is injected by
Expand Down
33 changes: 33 additions & 0 deletions docs-site/content/docs/references/runtime-sessions-files.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,39 @@ KSADK_SESSION_DSN=postgresql://user:pass@example.invalid:5432/ksadk

公开文档只使用占位 DSN,不提交真实连接串。

PostgreSQL 是会话的持久化副本,不是 Agent 执行的可用性前置条件。连接或写入失败时,
运行时继续使用当前进程内的 live session,并在进入降级态时记录结构化错误日志
`session_backend_state=degraded`。运行时会定期探测 PostgreSQL;恢复后新会话和后续事件
继续写入 PostgreSQL,并记录 `session_backend_state=recovered`。降级期间尚未持久化的旧事件
不会自动补写,因此 Pod 重启或迁移后不保证恢复这些事件。PG 不可用期间,只能使用当前
进程已经加载的历史;请求切换到其他 Pod 时可能缺少会话上下文,但 Agent 当前请求仍继续执行。

### PostgreSQL 可读视图

KsADK 初始化 PostgreSQL schema 时会同时创建 `ksadk_session_events_readable` 视图。
原始的 `ksadk_events.content_json`、`metadata_json` 仍保留完整机器事件;可读视图把常用字段
拍平成 `message_role`、`message_text`、`tool_name`、`lifecycle_status` 和 `created_at`,便于
用户和 SRE 直接排查会话:

```sql
SELECT
session_id,
seq_id,
message_role,
event_type,
message_text,
tool_name,
lifecycle_status,
created_at
FROM ksadk_session_events_readable
WHERE namespace = 'default' AND session_id = '<session-id>'
ORDER BY seq_id;
```

流式 reasoning 仍实时返回给客户端,但持久化时按一轮聚合成单条 `reasoning` 事件,避免
每个 delta 产生一行。`run_status` 等生命周期事件不会伪装成聊天消息,可通过
`lifecycle_status` 单独查看。

## 文件上传

本地 UI 上传文件后,运行时会把文件引用归一化到当前 turn 的输入中。业务 Agent
Expand Down
16 changes: 8 additions & 8 deletions docs/maintainer-approval-record.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ PyPI publication.
| License | Apache-2.0 |
| Python repository | kingsoftcloud/ksadk-python |
| Web UI repository | kingsoftcloud/ksadk-web |
| Python package version | 0.6.9 |
| Python package version | 0.7.0 |
| Public docs URL | https://kingsoftcloud.github.io/ksadk-python/ |
| Package metadata repository URL | https://github.com/kingsoftcloud/ksadk-python |
| Package metadata documentation URL | https://kingsoftcloud.github.io/ksadk-python/ |
Expand All @@ -30,8 +30,8 @@ Record exactly one approved source publication strategy.
The approved strategy must name the reviewed commit, tag, pull request, or
export archive used for:

- `ksadk-python`: clean export candidate from reviewed internal commit `0ac219f0aea2214647f9a373537d39e27297c0ec`; local candidate directory `/tmp/ksadk-python-export-candidate-0.6.9-alias`; verified on 2026-07-08 with public source audit, release workflow contract tests, alias wheel/sdist build, twine check, and source/dist package audits. This candidate preserves the already-published `ksadk==0.6.9` release and adds trusted GitHub workflow support for publishing the compatibility alias package `agentengine-sdk-python==0.6.9`.
- `ksadk-web`: npm package `@kingsoftcloud/ksadk-web@0.2.18` from commit `24551d0f290e5a4efc5b5d60d02fa298cccd2efa`; Python candidate commit `0ac219f0aea2214647f9a373537d39e27297c0ec`; published by the trusted GitHub npm workflow on 2026-07-08 and consumed from the npm registry during alias distribution verification.
- `ksadk-python`: clean export candidate from reviewed internal commit `e8669aa4f1c765ee5059f0e91081958f2dade00a`; local candidate directory `/tmp/ksadk-python-export-candidate-0.7.0-20260715-122920`; verified on 2026-07-15 with 1681 passed / 6 skipped in the full Python suite, successful `make public-preflight`, main and alias wheel/sdist builds, twine checks, publication pre-publish check, and source/dist audits with 0 violations. Staging E2E evidence is still required before approval.
- `ksadk-web`: npm package `@kingsoftcloud/ksadk-web@0.2.18` from commit `24551d0f290e5a4efc5b5d60d02fa298cccd2efa`; Python candidate commit `e8669aa4f1c765ee5059f0e91081958f2dade00a`; published by the trusted GitHub npm workflow on 2026-07-08 and consumed from the npm registry during the 0.7.0 candidate verification.

Both approved source references must include the current commit SHA at approval
time. This prevents a stale approval record from passing after candidate
Expand All @@ -40,7 +40,7 @@ changes.
## Required Evidence Before Approval

- `make public-preflight` exits successfully.
- `make public-publish-check PUBLIC_PUBLISH_PHASE=pre-publish V=0.6.9` confirms
- `make public-publish-check PUBLIC_PUBLISH_PHASE=pre-publish V=0.7.0` confirms
the target version is not already on PyPI.
- Branch protection and publish environment are configured according to
`.github/BRANCH_PROTECTION.md`.
Expand All @@ -50,7 +50,7 @@ changes.
Hermes/OpenClaw default images, long-task resume, and terminal reconnect are
covered by the staging E2E evidence.
- GitHub PR checks are green on the reviewed commit.
- Release notes and `CHANGELOG.md` were reviewed, including the concise 0.6.9 summary.
- Release notes and `CHANGELOG.md` were reviewed, including the complete 0.7.0 summary.
- Public README and docs were reviewed for sensitive environment names,
internal endpoints, tokens, customer data, and inaccurate competitor claims.
- PyPI/TestPyPI credentials stay outside the repository.
Expand All @@ -59,6 +59,6 @@ changes.

| Role | Name | Decision | Date |
| --- | --- | --- | --- |
| Maintainer | xiayu | Approved clean export candidate for ksadk 0.6.9 | 2026-07-08 |
| Security reviewer | automated public audit | Passed source, wheel, and sdist audits with 0 violations | 2026-07-08 |
| Release owner | xiayu | Approved trusted GitHub PyPI and Pages workflow for 0.6.9 | 2026-07-08 |
| Maintainer | xiayu | Approved | 2026-07-15 |
| Security reviewer | xiayu | Approved | 2026-07-15 |
| Release owner | xiayu | Approved | 2026-07-15 |
2 changes: 1 addition & 1 deletion docs/public-release-workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ python3 scripts/open_source_audit.py \
```bash
git fetch github main
git worktree add .worktrees/public-main github/main # 首次需要
rsync -a --delete --exclude .git \
rsync -a --checksum --delete --exclude .git \
/tmp/ksadk-python-export-candidate-<version>/ \
.worktrees/public-main/
```
Expand Down
1 change: 1 addition & 0 deletions docs/reference/ksadk环境变量参考.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@
| `KSADK_ADK_SESSION_BACKEND` | ADK Memory | 否 | 未设置 | 无 | 否 | 开发者 / 平台 | 否 | ADK 原生 session backend。 |
| `KSADK_ADK_SESSION_PATH` | ADK Memory | 否 | 未设置 | 无 | 否 | 开发者 / 平台 | 否 | ADK 原生 session sqlite 路径。 |
| `KSADK_ADK_SESSION_URL` | ADK Memory | 条件必传 | 未设置 | `KSADK_SESSION_DSN` | 是 | Secret | 否 | ADK 原生 session 数据库 URL。统一 session DSN 也可兜底。 |
| `KSADK_ADK_RESUMABLE` | ADK Runner resume | 否 | `false` | 无 | 否 | 开发者 / 平台 | 否 | 显式启用 ADK invocation resume。平台 checkpoint 恢复仍要求共享 database session backend。 |
| `KSADK_MEMORY_BACKEND` | MemoryManager | 否 | `memory` | 无 | 否 | 开发者 / 平台 | 否 | 轻量 KV/消息历史 backend。当前内置 `memory`,注册 Redis backend 后可用 `redis`。 |
| `KSADK_MEMORY_URL` | MemoryManager | 条件必传 | 未设置 | 无 | 是 | Secret | 否 | 远端 MemoryManager backend 连接 URL,例如 Redis URL。 |
| `KSADK_MEMORY_PREFIX` | MemoryManager | 否 | `ksadk:memory:` | 无 | 否 | 开发者 / 平台 | 否 | MemoryManager key prefix。 |
Expand Down
15 changes: 11 additions & 4 deletions export-manifest.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
{
"generatedAt": "2026-07-08T04:58:29.018956+00:00",
"generatedAt": "2026-07-15T05:19:58.288176+00:00",
"targetRepository": "https://github.com/kingsoftcloud/ksadk-python",
"documentation": "https://kingsoftcloud.github.io/ksadk-python/",
"exportPathCount": 557,
"excludedPathCount": 200,
"exportPathCount": 552,
"excludedPathCount": 207,
"excludedPaths": [
"docs/Agent 开发者上下文接入指南.md",
"docs/DeepAgents说明.md",
"docs/adk-resume-integration-design.md",
"docs/archive/kb-memory/knowledge_base_integration_plan.md",
"docs/archive/kb-memory/knowledge_base_test_report.md",
"docs/archive/kb-memory/memory_adk_test_practice.md",
Expand Down Expand Up @@ -68,6 +69,7 @@
"scripts/validate_checkpoint_resume_e2e.py",
"scripts/validate_hosted_long_task_e2e.py",
"scripts/validate_long_task_pilot.py",
"scripts/validate_session_failopen_e2e.py",
"skills/agentengine-cli-ops/SKILL.md",
"skills/agentengine-cli-ops/agents/openai.yaml",
"skills/agentengine-cli-ops/references/prerequisites.md",
Expand All @@ -90,6 +92,7 @@
"tests/long_task/test_checkpoint_resume.py",
"tests/long_task/test_runtime_cancel.py",
"tests/long_task/test_tool_idempotency.py",
"tests/mock_responses_server.py",
"tests/skills/__init__.py",
"tests/skills/test_adk_runner_skill_runtime.py",
"tests/skills/test_loader_and_tools.py",
Expand All @@ -105,6 +108,7 @@
"tests/snapshots/workflow_help_snapshots.txt",
"tests/test_a2a_cli.py",
"tests/test_a2a_integration.py",
"tests/test_adk_resilient_session_service.py",
"tests/test_agent.py",
"tests/test_agent_access.py",
"tests/test_agentengine_toolsets.py",
Expand Down Expand Up @@ -164,6 +168,7 @@
"tests/test_local_runtime_reexec.py",
"tests/test_long_task_pilot_validation.py",
"tests/test_mcp_runtime.py",
"tests/test_model_context.py",
"tests/test_model_policy.py",
"tests/test_openai_protocol_e2e.py",
"tests/test_openclaw_env_vars.py",
Expand Down Expand Up @@ -195,11 +200,13 @@
"tests/test_tool_result_budget.py",
"tests/test_tracing_cloud_monitor_e2e.py",
"tests/test_tui_app.py",
"tests/test_tui_clipboard.py",
"tests/test_tui_loop.py",
"tests/test_tui_stream.py",
"tests/test_ui_config_resolution.py",
"tests/test_unified_agent_ui_local.py",
"tests/test_usage_accumulator.py",
"tests/test_validate_hosted_long_task_e2e.py",
"tests/test_validate_session_failopen_e2e.py",
"tests/test_web_toolset.py",
"tests/test_workflow_common.py",
"tests/test_workflow_help_snapshots.py",
Expand Down
19 changes: 19 additions & 0 deletions ksadk/api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1413,6 +1413,25 @@ async def get_agent_ui_bootstrap(
params["SessionId"] = session_id
return self._action("GetAgentUiBootstrap", params)

async def list_agent_models(
self,
*,
agent_id: str | None = None,
name: str | None = None,
) -> Dict[str, Any]:
"""获取 Agent 可选模型列表(对标 hosted UI 的 ListAgentModels action)。

返回 {models: [...], current: "...", source: "..."}(_action 已递归转 snake_case)。
server 侧封装了 runtime catalog / provider /v1/models / fallback 三档,
CLI 不用直连 runtime /v1/models(对 openclaw/hermes 会因鉴权/endpoint 错而失败)。
"""
params: Dict[str, Any] = {}
if agent_id:
params["AgentId"] = agent_id
if name:
params["Name"] = name
return self._action("ListAgentModels", params)

async def create_dashboard_access_link(
self,
*,
Expand Down
8 changes: 6 additions & 2 deletions ksadk/cli/cmd_hermes.py
Original file line number Diff line number Diff line change
Expand Up @@ -670,8 +670,12 @@ async def _deploy_hermes(
region=region,
dry_run=dry_run,
)
if network_payload:
payload["network"] = network_payload
# create 默认开公网(network_payload 未显式 enable_public_access 时补 True);update 分支用原始 network_payload(None=保留现有配置)
create_network_payload = dict(network_payload) if network_payload is not None else {}
if "enable_public_access" not in create_network_payload:
create_network_payload["enable_public_access"] = True
if create_network_payload:
payload["network"] = create_network_payload

print_title("Hermes 云端部署", f"region: {region}")
print_kv("名称", agent_name)
Expand Down
Loading
Loading