Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
18fa248
feat(cli): add veadk mpa create for one-click mpa-agent provisioning
superops-team Sep 11, 2026
74fc82b
feat(cli): provision mpa agents with AgentKit runtime
superops-team Sep 11, 2026
8381398
feat(studio): stream A2A runtime events
superops-team Sep 12, 2026
c94e7a1
docs(studio): record A2A streaming verification
superops-team Sep 12, 2026
93fbfdc
docs(studio): design tool activity visualization
superops-team Sep 12, 2026
bca1fe4
feat(studio): visualize tool activities
superops-team Sep 12, 2026
cc425da
fix(studio): keep slow A2A streams alive
superops-team Sep 12, 2026
923b01c
fix(studio): preserve A2A reasoning stream
superops-team Sep 12, 2026
b5f61d2
fix(studio): finalize streamed A2A replies
superops-team Sep 12, 2026
8b4667f
fix(studio): complete A2A delta-only replies
superops-team Sep 12, 2026
95e4079
fix(studio): preserve appended A2A events
superops-team Sep 12, 2026
0d0bced
fix(studio): keep A2A artifact event identities unique
superops-team Sep 12, 2026
25e253d
feat(studio): harden mpa runtime control plane
superops-team Sep 14, 2026
a9d4566
feat(studio): simplify session settings rail
superops-team Sep 14, 2026
ba781d3
fix(studio): filter mpa agents by runtime tag
superops-team Sep 14, 2026
0cd5201
feat(studio): show selected Runtime MPA scheduled tasks
chenzhenghui-arch Sep 15, 2026
a1353d5
feat(studio): obtain MPA task credentials through TOP
chenzhenghui-arch Sep 15, 2026
e5830f0
feat(studio): read all Runtime cron tasks without JWT acquisition
chenzhenghui-arch Sep 15, 2026
9299cf1
feat(studio): manage Runtime scheduled tasks with mono-style views
chenzhenghui-arch Sep 15, 2026
2fe0602
fix(studio): infer scheduled task agent from runtime
chenzhenghui-arch Sep 15, 2026
e523cc7
fix(studio): let runtime resolve scheduled task agent name
chenzhenghui-arch Sep 15, 2026
768bc94
fix(mpa): disable JWT by default for VeADK provisioning
chenzhenghui-arch Sep 15, 2026
915f742
fix(studio): preserve long-running A2A waits and show task status
chenzhenghui-arch Sep 15, 2026
480f075
fix(studio): align Runtime task identity and ignore user stream echoes
chenzhenghui-arch Sep 15, 2026
ee0ad93
fix(studio): preserve reply identity across history turns
chenzhenghui-arch Sep 17, 2026
ac36331
merge: include MPA default JWT provisioning in Studio integration
chenzhenghui-arch Sep 17, 2026
2d916d7
feat(studio): download sandbox files from conversation links
chenzhenghui-arch Sep 17, 2026
b4d5d62
style(studio): put sandbox download buttons on separate lines
chenzhenghui-arch Sep 17, 2026
b9b3c50
Merge pull request #1 from PolarisCzh/czh/studio-cron-e2e
superops-team Sep 17, 2026
ca85332
fix(mpa): disable database auto-instrumentation by default
chenzhenghui-arch Sep 17, 2026
0f83fd0
Merge pull request #2 from PolarisCzh/czh/runtime-disable-db-spans
superops-team Sep 18, 2026
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
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -213,5 +213,15 @@ agentkit.yaml
agentkit*.yaml
.agentkit/

# veadk mpa create config (contains PG/model/OpenViking/Feishu secrets).
# Only the committed *.example.yaml template is allowed.
mpa-create.config.yaml
mpa-create.config*.yaml
!mpa-create.config.example.yaml
**/mpa-create.config.yaml
**/mpa-create.config*.yaml
!**/mpa-create.config.example.yaml

# PiAgent release archives are downloaded and verified during image builds.
examples/piagent_with_mcp/vendor/pi-*.tar.gz
.gstack/
66 changes: 59 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,61 @@
# Agent Instructions

- Do not use `codex/` as a branch name prefix in this repository. Use semantic branch prefixes such as `feat/`, `fix/`, `chore/`, or `docs/`; for example, `feat/pr-748-dev`.
- Before modifying frontend code, read `frontend/SPEC.md`.
- When the user describes a requirement, propose an implementation plan before changing code, and wait for the user to be satisfied before making edits.
- After creating or switching to a new branch, run `git pull` before development. Branch names must use semantic prefixes and reflect the requirement content.
- When committing, include only changes related to the current feature or fix.
- Before committing, fetch the latest remote code, rebase the branch onto it, then run pre-commit and unit tests.
- When execution hits a pitfall such as insufficient permissions or missing dependencies, ask the user whether to document that pitfall.
VeADK includes a Python SDK, CLI/runtime integrations, and AgentKit Studio with a TypeScript/React frontend and supporting Python services. Base decisions on the relevant implementation, tests, and existing contracts rather than assumptions from another repository.

## Language and document ownership

- Keep this repository-wide development standard in English. Use English for new code identifiers, comments, and docstrings; user-facing text follows the owning area's localization rules.
- Read [prd-spec/README.md](prd-spec/README.md) before creating or updating a change design. Every PRD/design must have complete English `.md` and Chinese `.zh.md` counterparts, sharing the same directory, date, and basename.
- Read [specs/README.md](specs/README.md) before defining or changing a component contract. Maintain each component under `specs/<component>/README.md` and `README.zh.md`.
- Keep both languages semantically equivalent and update them in the same change. Preserve identifiers, commands, examples, limits, and acceptance criteria across translations. Missing or conflicting counterparts block approval and delivery.
- PRDs own change-specific intent, scope, tasks, and acceptance; component specs own maintained responsibilities, interfaces, state, data, and failure semantics. Link them rather than duplicate contracts.
- Before modifying frontend code, read `frontend/SPEC.md`; also apply it to its supporting backend interfaces as specified there. It remains the Studio development standard and is not replaced or translated by this document.
- Preserve existing user-documentation conventions: the documentation site uses Chinese `.mdx` and English `.en.mdx`; bilingual module/example READMEs use English `README.md` and Chinese `README.zh.md`.

## Required development workflow

1. **Inspect and agree on scope.** Read the affected implementation, tests, and contracts. When the user describes a requirement, propose an implementation plan and wait for the user to be satisfied before making edits. Distinguish verified facts from assumptions.
2. **Design before implementation.** Features, refactors, and bugfixes require a bilingual PRD under `prd-spec/features/`, `prd-spec/refactors/`, or `prd-spec/bugfixes/`. Include background/evidence, goals, non-goals, scenarios, requirements, design, affected files, tasks, tests, risks, and acceptance criteria.
3. **Assess component contracts.** Create or update affected bilingual component specs for changes to ownership, APIs, configuration, state/data, events, permissions, security, compatibility, runtime behavior, or observability. Record a justified no-impact conclusion when no component contract changes. Do not backfill unrelated components.
4. **Clear design review.** Review PRD/spec consistency, feasibility, boundaries, errors, security, compatibility, testability, and bilingual equivalence. Use the available `review-spec` skill; if unavailable, perform and record the same review directly. Resolve blockers and record user approval before modifying production code or tests. A generic skill's Chinese-only default does not override this repository's bilingual rule.
5. **Implement against the approved design.** Map changes to requirements/tasks, write a failing regression or contract test first, then implement and refactor within scope. Contract or scope changes return to design review before implementation proceeds.
6. **Verify and review.** Run affected tests first, then required repository and component gates. Review both implementation correctness and edge cases, resource handling, security, test quality, and contract alignment. Fix blocking findings and rerun affected checks.
7. **Reconcile and deliver.** Synchronize both document languages, component contracts, affected user docs/examples, and required generated artifacts. Record actual verification commands, results, unverified areas, and remaining risks. All agreed tasks and acceptance criteria must be satisfied before declaring completion; deferred scope requires user agreement.

Pure documentation, translation, or formatting changes that preserve runtime behavior and public contracts do not need a recursive PRD. They still require an agreed approach, applicable bilingual updates, and proportionate checks. This exception includes maintaining these development guidelines; it does not exempt code or behavioral changes.

## Implementation boundaries

- Make the smallest complete change that satisfies the approved requirement. Reuse existing modules and dependencies; avoid unrelated cleanup, speculative abstractions, and partially wired features.
- Treat public Python imports/signatures, CLI/configuration behavior, generated projects, Studio API types, and runtime/event contracts as consumer-facing boundaries. Breaking changes require explicit approval and a plan for affected callers and data; do not copy another project's blanket no-compatibility policy.
- Cover asynchronous cancellation, timeouts, late responses/events, terminal states, and resource cleanup where affected. Do not turn errors into silent success or empty results.
- Keep real credentials, signed URLs, personal data, and unredacted production logs out of source, design documents, reports, test fixtures, and generated artifacts.
- Isolate tests from real user state and external services by default. Real cloud/provider operations need explicit authorization and an isolated smoke/E2E procedure; report simulated and live verification separately.

## Verification gates

Use the repository-local Python environment and current `pyproject.toml`, `pytest.ini`, package scripts, and CI workflows as command references. Do not invent `make` targets, copy another repository's coverage thresholds, or treat an unavailable check as passing.

| Change area | Required verification |
| --- | --- |
| Python SDK, CLI, and backend | Targeted tests via `uv run --extra dev pytest <test-paths>`; broader regression tests when shared contracts or dependencies are affected. |
| Default parallel Python regression | `uv run --extra dev pytest -n 2 -m "not codex_smoke and not piagent_smoke"`; adjust worker count to available resources and record the selection. Explicit smoke runs are separate. |
| Codex runtime smoke | When affected and the environment is prepared: `CODEX_RUN_SMOKE=1 uv run --extra dev pytest -m codex_smoke -p no:xdist -rs`. This test starts real processes and binds ports; never run it under parallel pytest. Verify it actually ran rather than skipped. |
| Studio frontend | `npm --prefix frontend test` and `npm --prefix frontend run build`, plus real browser checks of the normal flow and affected loading, empty, error, cancellation, retry, keyboard/IME, and narrow-window cases. Follow `frontend/SPEC.md` for additional checks and release asset requirements. |
| Studio backend or generated Python | Targeted Python tests plus Ruff and Pyright for changed Python files, as required by `frontend/SPEC.md`; verify generated code, dependencies, configuration, and deployment payloads together. |
| Harness/sidecar contracts | The affected checks and existing coverage thresholds in `.github/workflows/harness-sidecar-release-gate.yaml`, including `npm --prefix frontend run test:harness-sidecar-coverage` when frontend sidecar contracts change. |
| PRD/spec and guideline-only changes | Check paired-language completeness, contract/identifier consistency, relative links, referenced paths/commands, and diff whitespace. No runtime test result may be claimed from documentation checks. |
| User documentation site | The affected Markdown/MDX checks and build/type checks defined in `docs/package.json`; do not apply site-specific tooling to unrelated plain Markdown without checking its scope. |

- Before committing, run `uv run --extra dev pre-commit run --all-files` and unit tests after synchronizing the branch as described below. Pre-commit includes Ruff and secret scanning; it does not replace browser, integration, or runtime verification.
- Prefer targeted checks during iteration. Expand to affected integration/E2E and regression gates for shared or high-risk changes and final delivery; explain any omitted required check.
- Record check outcomes as `pass`, `fail`, `blocked`, `not_run`, or `not_applicable`, with reasons for the last three. Include the tested revision/diff scope and execution date. Skipped tests do not prove the relevant behavior.
- Keep change-specific review and verification summaries in the bilingual PRD by default. Separate evidence artifacts are optional when useful; OpenSpec and a multi-report hierarchy are not prerequisites.

## Git and execution safety

- Do not use `codex/` as a branch name prefix. Use semantic prefixes such as `feat/`, `fix/`, `chore/`, or `docs/`, with a name reflecting the requirement.
- After creating or switching to a new branch, run `git pull` before development. If no upstream exists or synchronization fails, resolve the target explicitly rather than guessing or bypassing the requirement.
- Before committing, fetch the latest remote code, rebase the branch onto the intended remote base, then run pre-commit and unit tests. Preserve unrelated user changes and stop if safe synchronization requires a user decision.
- Commit only changes related to the current feature or fix. Commit, push, PR creation, publication, and deployment require user authorization; approval of a design does not authorize them.
- When execution hits a pitfall such as insufficient permissions or missing dependencies, ask the user whether to document that pitfall. Report blocked checks honestly and do not alter machine-global configuration or bypass gates to hide the issue.
30 changes: 30 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1047,3 +1047,33 @@ Sandbox。修改这些模板只需要更新 Studio,不需要重建镜像,也
模板中的新依赖不会自动安装,运行环境依赖仍由镜像管理。

其他地域需要显式设置 `STUDIO_WORKSPACE_IMAGE`,避免错误使用跨地域镜像。

### MPA Runtime scheduled tasks

Select a connected cloud Runtime and open the Runtime scheduled tasks tab.
Studio uses gateway authentication to call `/api/v1/esa-cron-tasks`, without TOP
credential acquisition, enterprise UID configuration, JWT or user identity headers.
The MPA Runtime must have `DISABLE_JWT_AUTH=true` and support all-user read access
(commit `833c6bc` or later). Gateway authentication and Studio Runtime authorization
remain enforced. The operator must enable this mode on the Runtime explicitly;
Studio never changes the authentication setting.

The list shows all users' tasks in the selected Runtime's configured store, with
search, pagination, prompt details, execution counts and success rate. Errors are
not rendered as empty results. No task mutations are performed.

Run `npm run test:mpa-cron-coverage` and
`python -m pytest tests/frontend/server/test_mpa_cron.py --cov=frontend.server.mpa_cron --cov-branch --cov-fail-under=96`
for isolated client/server checks.

### Runtime task management (2026-09-15)

Runtime tasks now follow mono's list/calendar workflow: status filtering, creation, editing, copying, deletion, enable/disable, run now, and execution history. Select a cloud Runtime first. The server forwards the authenticated Studio user as `x-user-id`; with MPA JWT disabled, that user's task data remains isolated. No JWT input or TOP credential exchange is used. Enter the Runtime's Agent ID when creating a task. Complex Cron expressions display only the server's next execution in the calendar. Mutations and history use the existing MPA REST interfaces; Runtime upgrades and ADK session authentication are separate concerns.

### A2A 长耗时请求

连接 A2A Runtime 后,对话会显示等待响应、排队或执行中的状态。收到有效状态后会继续等待最终回复,不因任务耗时超过 30 秒而自动中断。等待响应不代表 Runtime 已接受任务;错误或连接中断也不代表后台任务已取消,请先确认任务状态再重试创建等操作。

### Sandbox file downloads

Assistant Markdown links under `/data/output/` or `/data/workspace/` appear as download buttons in conversation history and streaming messages. Studio uses the current Runtime and session through its authenticated proxy; files remain available only while that Sandbox and file exist. Legacy `<file-card>` and `<personal-drive-enable-card>` payloads are hidden in conversation rendering. A failed download can be retried by clicking the button again. Run `npm run test:sandbox-download-coverage` for the focused regression suite.
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"build": "node scripts/build.mjs",
"test": "node --test tests/*.test.mjs",
"check:i18n": "node scripts/check-i18n.mjs",
"test:sandbox-download-coverage": "vitest run --coverage -c vitest.sandbox-download.config.ts",
"test:mpa-cron-coverage": "vitest run --coverage -c vitest.mpa-cron.config.ts",
"test:webui-assets": "node scripts/verifyBuiltAssets.mjs",
"test:visualizations": "node scripts/testVisualizationCompatibility.mjs",
"test:harness-sidecar-coverage": "vitest run --coverage -c vitest.harness-sidecar.config.ts",
Expand Down
182 changes: 182 additions & 0 deletions frontend/server/mpa_cron.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
"""User-scoped task management through authorized MPA Runtime connections."""

import asyncio
from collections.abc import Callable
from typing import Any

import httpx
from fastapi import FastAPI, HTTPException, Path, Query, Request


async def task_request(
endpoint: str,
authorization: str,
user_id: str,
method: str,
suffix: str = "",
params: dict | None = None,
payload: dict | None = None,
) -> dict[str, Any]:
if not user_id:
raise HTTPException(401, "mpa_identity_required")
try:
async with httpx.AsyncClient(timeout=30, follow_redirects=False) as client:
response = await client.request(
method,
endpoint.rstrip("/") + "/api/v1/esa-cron-tasks" + suffix,
headers={"Authorization": authorization, "x-user-id": user_id},
params=params,
json=payload,
)
if not response.is_success:
raise HTTPException(
response.status_code if response.is_error else 502,
"mpa_tasks_failed",
)
data = response.json()
if not isinstance(data, dict):
raise TypeError("Invalid task response")
return data
except (httpx.HTTPError, ValueError, TypeError) as error:
raise HTTPException(502, "mpa_upstream_failed") from error


def mount_routes(
app: FastAPI,
*,
authorize: Callable,
connection: Callable,
authorization: Callable,
region_for: Callable,
user_for: Callable,
) -> None:
async def send(
request, runtime_id, region, method, suffix="", params=None, payload=None
):
region = region_for(region)
runtime = await asyncio.to_thread(authorize, request, runtime_id, region)
user_id = user_for(request)
endpoint, apikey, auth_type, _ = await asyncio.to_thread(
connection, runtime_id, region, runtime
)
return await task_request(
endpoint,
authorization(request, apikey, auth_type),
user_id,
method,
suffix,
params,
payload,
)

async def body(request: Request, allowed: set[str]):
raw = await request.body()
if len(raw) > 32768:
raise HTTPException(413, "mpa_payload_too_large")
try:
payload = await request.json()
except ValueError as error:
raise HTTPException(422, "mpa_invalid_payload") from error
if not isinstance(payload, dict) or set(payload) - allowed:
raise HTTPException(422, "mpa_invalid_payload")
return payload

fields = {
"name",
"agentId",
"prompt",
"enabled",
"schedule",
"delivery",
"jitterSeconds",
"timeoutSeconds",
}

@app.get("/web/mpa-cron/{runtime_id}")
async def get_tasks(
request: Request,
runtime_id: str,
region: str,
offset: int = Query(0, ge=0),
query: str = Query("", max_length=200),
):
return await send(
request,
runtime_id,
region,
"GET",
params={
"includeDisabled": "true",
"limit": 20,
"offset": offset,
"query": query,
},
)

@app.post("/web/mpa-cron/{runtime_id}")
async def create_task(request: Request, runtime_id: str, region: str):
return await send(
request,
runtime_id,
region,
"POST",
payload=await body(request, fields | {"clientToken"}),
)

@app.post("/web/mpa-cron/{runtime_id}/{task_id}")
async def update_task(
request: Request,
runtime_id: str,
region: str,
task_id: str = Path(pattern=r"^[A-Za-z0-9_-]+$"),
):
return await send(
request,
runtime_id,
region,
"POST",
"/" + task_id,
payload=await body(request, fields | {"expectedVersion"}),
)

@app.delete("/web/mpa-cron/{runtime_id}/{task_id}")
async def delete_task(
request: Request,
runtime_id: str,
region: str,
task_id: str = Path(pattern=r"^[A-Za-z0-9_-]+$"),
):
return await send(request, runtime_id, region, "DELETE", "/" + task_id)

@app.post("/web/mpa-cron/{runtime_id}/{task_id}/run")
async def run_task(
request: Request,
runtime_id: str,
region: str,
task_id: str = Path(pattern=r"^[A-Za-z0-9_-]+$"),
):
return await send(
request,
runtime_id,
region,
"POST",
"/" + task_id + "/run",
payload=await body(request, {"clientToken", "mode"}),
)

@app.get("/web/mpa-cron/{runtime_id}/{task_id}/runs")
async def get_runs(
request: Request,
runtime_id: str,
region: str,
task_id: str = Path(pattern=r"^[A-Za-z0-9_-]+$"),
offset: int = Query(0, ge=0),
):
return await send(
request,
runtime_id,
region,
"GET",
"/" + task_id + "/runs",
params={"offset": offset, "limit": 20},
)
Loading