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
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Set up JDK 17
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'temurin'
Expand All @@ -32,7 +32,7 @@ jobs:

- name: Upload test reports
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: test-reports
path: |
Expand All @@ -46,10 +46,10 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Set up JDK 17
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'temurin'
Expand All @@ -60,7 +60,7 @@ jobs:

- name: Upload sample test reports
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: direct-sample-test-reports
path: samples/target/surefire-reports/
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:

steps:
- name: Checkout (full history for tag ancestry validation)
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

Expand Down Expand Up @@ -80,7 +80,7 @@ jobs:
test -n "${SIGNING_PASSWORD}" || { echo "SIGNING_PASSWORD is not set"; exit 1; }

- name: Set up JDK
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '17'
Expand Down
17 changes: 14 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# Changelog

## [Unreleased] — 1.0.0 release candidate
## [Unreleased]

- Release streaming resources when publisher subscription setup throws synchronously.
- Align published dependency examples with 0.0.2 and refresh neutral architecture terminology.
- Update GitHub Actions to Node 24-compatible action versions.

## [0.0.2] — 2026-09-07

- Publish the main-branch baseline under `net.openan.workflow.sdk`, including the parent POM,
workflow-engine and spring-boot-starter. This tag has the same source tree as 0.0.1.

## [0.0.1] — 2026-09-04

- Use published A2A-T 1.1.0 from Maven Central; remove SDK source checkout/install from CI; move content generation,
validation, templates and SDK initialization to the host.
Expand All @@ -25,5 +36,5 @@
- Publish a compiled host integration example and require sample regression tests.
- Keep documentation host-neutral; sample class and AgentCard identifiers remain unchanged.

This repository prepares the initial 1.0.0 SDK release. Earlier internal development notes are not published API
contracts or evidence of a Maven release. Release publication/tagging is a separate, explicitly authorized operation.
Published Maven artifacts use the version selected by the release tag. The default source-build
`revision=1.0.0` is a development version, not the version to use when consuming Maven Central artifacts.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ subscription remains open until the host-defined terminal event, explicit cancel

### 1. Add Maven dependency

The current engine release is `0.0.2` on [Maven Central](https://repo.maven.apache.org/maven2/net/openan/workflow/sdk/).

A2A-T SDK `1.1.0` is published to Maven Central. Maven resolves it automatically; no SDK source checkout or local SDK
build is required. The engine depends only on
`a2a-t-core`; host agents using content generation explicitly add `a2a-t-client:1.1.0`. A dispatched-agent service that
Expand All @@ -49,7 +51,7 @@ upgrade guidance.
<dependency>
<groupId>net.openan.workflow.sdk</groupId>
<artifactId>workflow-engine</artifactId>
<version>1.0.0</version>
<version>0.0.2</version>
</dependency>
```

Expand All @@ -59,7 +61,7 @@ For Spring Boot server-side integration:
<dependency>
<groupId>net.openan.workflow.sdk</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>1.0.0</version>
<version>0.0.2</version>
</dependency>
```

Expand Down
6 changes: 3 additions & 3 deletions docs/en/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ flowchart TB
direction LR
ORCH["Orchestration center<br/>workflow definitions (PSOP)"]
REGT["Registry center<br/>AgentCards"]
OMC["Dispatched agents (OMC)"]
DISPATCHED["Dispatched agents"]
end

WB ==>|"selects workflow and starts"| EXE
Expand All @@ -181,7 +181,7 @@ flowchart TB
TRANS --> OBSV
TRANS --> A2AJ
MSG -.->|"only reference site inside the engine"| A2ATC
A2AJ -->|"Task-T · Negotiation-T<br/>Authorization-T · Notification-T"| OMC
A2AJ -->|"Task-T · Negotiation-T<br/>Authorization-T · Notification-T"| DISPATCHED
REGC -->|"workflow search"| ORCH
REGC -->|"AgentCard retrieval"| REGT
```
Expand All @@ -190,7 +190,7 @@ Key properties of the module view: the engine is embedded in the host process as
by host code and extended through the callbacks. The scheduling kernel (core/control/model packages)
references no A2A-T SDK types — a boundary guarded by the `ContentDependencyBoundaryTest` architecture test.
The client protocol adaptation layer (A2ATExtension, A2atMessages, DefaultWorkflowEngineClient) is the only
place inside the engine that references a2a-t-sdk. All four interaction types with dispatched agents (OMC) —
place inside the engine that references a2a-t-sdk. All four interaction types with dispatched agents —
Task-T, Negotiation-T, Authorization-T, Notification-T — travel over a2a-java-sdk transports, with
authorization and subscription on channels independent of the workflow. The orchestration and registry
centers are only reached by the engine clients for workflow-definition search and AgentCard retrieval; the
Expand Down
2 changes: 1 addition & 1 deletion docs/en/DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Add to your `pom.xml`:
<dependency>
<groupId>net.openan.workflow.sdk</groupId>
<artifactId>workflow-engine</artifactId>
<version>1.0.0</version>
<version>0.0.2</version>
</dependency>
```

Expand Down
10 changes: 5 additions & 5 deletions docs/en/INTEGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ callbacks own A2A-T generation, semantic validation, schemas and any LLM calls.
<dependency>
<groupId>net.openan.workflow.sdk</groupId>
<artifactId>workflow-engine</artifactId>
<version>1.0.0</version>
<version>0.0.2</version>
</dependency>
```

Expand Down Expand Up @@ -220,18 +220,18 @@ configuration without modifying system properties. Never log plaintext or the ke

**Encrypt a password**

Build the jar with `mvn -pl workflow-engine -am package`; commands below run from the repository root.
Build the jar with `mvn -pl workflow-engine -am -Drevision=0.0.2 package`; commands below run from the repository root.
`set` is Windows cmd syntax (PowerShell: `$env:A2AT_CRED_KEY='...'`). This CLI needs only the SDK jar and JDK.
Use disposable example values here: command-line passwords/keys can appear in shell history and process listings.
For production, obtain secrets securely in the host and use the Java encryption API.

```bash
# Option 1: set env var first
set A2AT_CRED_KEY=4f8a2b1c3d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b
java -cp workflow-engine/target/workflow-engine-1.0.0.jar dev.openan.workflow.engine.client.CredentialCrypto "Admin@123"
java -cp workflow-engine/target/workflow-engine-0.0.2.jar dev.openan.workflow.engine.client.CredentialCrypto "Admin@123"

# Option 2: pass key as second argument
java -cp workflow-engine/target/workflow-engine-1.0.0.jar dev.openan.workflow.engine.client.CredentialCrypto "Admin@123" 4f8a2b1c3d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b
java -cp workflow-engine/target/workflow-engine-0.0.2.jar dev.openan.workflow.engine.client.CredentialCrypto "Admin@123" 4f8a2b1c3d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b
```

Output:
Expand All @@ -247,7 +247,7 @@ Paste the output into the `value` field of the credentials JSON.
1. Generate a new key: `openssl rand -hex 32`
2. Update the host secret store / explicit `credentialEncryptionKey`, or its OS/JVM `A2AT_CRED_KEY`
3. Re-encrypt all passwords:
`java -cp workflow-engine/target/workflow-engine-1.0.0.jar dev.openan.workflow.engine.client.CredentialCrypto "plaintext" new-key`
`java -cp workflow-engine/target/workflow-engine-0.0.2.jar dev.openan.workflow.engine.client.CredentialCrypto "plaintext" new-key`
4. Update the `enc:...` results in the credentials JSON file

> The `.env` file should not be committed to version control. Add it to `.gitignore`.
Expand Down
6 changes: 3 additions & 3 deletions docs/zh/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ flowchart TB
direction LR
ORCH["编排中心<br/>工作流定义(PSOP)"]
REGT["注册中心<br/>AgentCard"]
OMC["被调度智能体(OMC)"]
DISPATCHED["被调度智能体"]
end

WB ==>|"选择工作流并启动"| EXE
Expand All @@ -170,15 +170,15 @@ flowchart TB
TRANS --> OBSV
TRANS --> A2AJ
MSG -.->|"引擎内唯一引用位置"| A2ATC
A2AJ -->|"Task-T · Negotiation-T<br/>Authorization-T · Notification-T"| OMC
A2AJ -->|"Task-T · Negotiation-T<br/>Authorization-T · Notification-T"| DISPATCHED
REGC -->|"检索工作流"| ORCH
REGC -->|"获取 AgentCard"| REGT
```

模块视图要点:引擎以 Maven 依赖嵌入宿主进程,由宿主代码启动并实现回调;调度内核(core/control/model
包)不引用任何 A2A-T SDK 类型,该边界由 `ContentDependencyBoundaryTest` 架构测试守护;client 协议
适配层(A2ATExtension、A2atMessages、DefaultWorkflowEngineClient)是引擎内引用 a2a-t-sdk 的唯一
位置;与被调度智能体(OMC)的 Task-T、Negotiation-T、Authorization-T、Notification-T 四类交互全部
位置;与被调度智能体的 Task-T、Negotiation-T、Authorization-T、Notification-T 四类交互全部
经 a2a-java-sdk 传输,授权与订阅使用独立于工作流的通道;编排中心与注册中心仅在工作流定义检索和
AgentCard 获取时被引擎客户端访问,检索与选择策略属宿主职责。任务创建前被对端以非 2xx 和标准
A2A 错误信封拒绝的调用,由传输层识别并投影为稳定错误码(`a2a.<reason>`),不进入协商、不自动重试;
Expand Down
2 changes: 1 addition & 1 deletion docs/zh/DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<dependency>
<groupId>net.openan.workflow.sdk</groupId>
<artifactId>workflow-engine</artifactId>
<version>1.0.0</version>
<version>0.0.2</version>
</dependency>
```

Expand Down
10 changes: 5 additions & 5 deletions docs/zh/INTEGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ A2A-T 工作流执行引擎是一个 Java SDK,用于基于 A2A 协议和 A2A-T
<dependency>
<groupId>net.openan.workflow.sdk</groupId>
<artifactId>workflow-engine</artifactId>
<version>1.0.0</version>
<version>0.0.2</version>
</dependency>
```

Expand Down Expand Up @@ -212,17 +212,17 @@ A2AT_CRED_KEY=4f8a2b1c3d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b

**加密密码**

先执行 `mvn -pl workflow-engine -am package`,以下命令在仓库根目录运行,仅需 SDK jar 和 JDK。
先执行 `mvn -pl workflow-engine -am -Drevision=0.0.2 package`,以下命令在仓库根目录运行,仅需 SDK jar 和 JDK。
`set` 是 Windows cmd 语法,PowerShell 应使用 `$env:A2AT_CRED_KEY='...'`。
以下参数仅用于演示;命令行口令/密钥可能进入终端历史和进程参数。生产应由集成方安全读取密钥并调用 Java 加密 API。

```bash
# 方式一:先设置环境变量
set A2AT_CRED_KEY=4f8a2b1c3d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b
java -cp workflow-engine/target/workflow-engine-1.0.0.jar dev.openan.workflow.engine.client.CredentialCrypto "Admin@123"
java -cp workflow-engine/target/workflow-engine-0.0.2.jar dev.openan.workflow.engine.client.CredentialCrypto "Admin@123"

# 方式二:密钥作为第二个参数
java -cp workflow-engine/target/workflow-engine-1.0.0.jar dev.openan.workflow.engine.client.CredentialCrypto "Admin@123" 4f8a2b1c3d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b
java -cp workflow-engine/target/workflow-engine-0.0.2.jar dev.openan.workflow.engine.client.CredentialCrypto "Admin@123" 4f8a2b1c3d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b
```

输出:
Expand All @@ -237,7 +237,7 @@ enc:uHQcTeKZMVNRM9Ga:o5vm4weRozBXBs04phrLq7j7+/yRVyDsrw==

1. 生成新密钥:`openssl rand -hex 32`
2. 更新集成方密钥存储及显式 `credentialEncryptionKey`,或 OS/JVM 的 `A2AT_CRED_KEY`;引擎不自动加载 `.env`
3. 用新密钥重新加密所有密码:`java -cp workflow-engine/target/workflow-engine-1.0.0.jar dev.openan.workflow.engine.client.CredentialCrypto "明文密码" 新密钥`
3. 用新密钥重新加密所有密码:`java -cp workflow-engine/target/workflow-engine-0.0.2.jar dev.openan.workflow.engine.client.CredentialCrypto "明文密码" 新密钥`
4. 将新的 `enc:...` 结果更新到凭证 JSON 文件

> `.env` 文件不应提交到版本库,建议加入 `.gitignore`。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ private static void requireStreamingSupport(AgentCard agentCard)
}
}

private static void writeStream(
static void writeStream(
HttpExchange exchange,
Flow.Publisher<StreamingEventKind> publisher,
ServerCallContext context)
Expand All @@ -652,7 +652,7 @@ private static void writeStream(
CountDownLatch done = new CountDownLatch(1);
OutputStream output = exchange.getResponseBody();
StreamCancellation cancellation = new StreamCancellation(context);
publisher.subscribe(
Flow.Subscriber<StreamingEventKind> subscriber =
new Flow.Subscriber<>() {
@Override
public void onSubscribe(Flow.Subscription subscription) {
Expand All @@ -667,14 +667,16 @@ public void onNext(StreamingEventKind item) {
formatSse(seq.incrementAndGet(), payload).getBytes(StandardCharsets.UTF_8));
output.flush();
cancellation.requestNext();
} catch (IOException error) {
} catch (Exception error) {
log.error("[SSE] Write failed for {}: {}", exchange.getRequestURI(), error.getMessage(), error);
cancellation.release();
done.countDown();
}
}

@Override
public void onError(Throwable error) {
log.error("[SSE] Stream failed for {}: {}", exchange.getRequestURI(), error.getMessage(), error);
cancellation.release();
done.countDown();
}
Expand All @@ -684,11 +686,15 @@ public void onComplete() {
cancellation.release();
done.countDown();
}
});
};
try {
publisher.subscribe(subscriber);
done.await();
} catch (InterruptedException error) {
Thread.currentThread().interrupt();
} catch (RuntimeException error) {
// HTTP 200 is already committed; close the stream without attempting a second response.
log.error("[SSE] Subscription failed for {}: {}", exchange.getRequestURI(), error.getMessage(), error);
} finally {
cancellation.release();
output.close();
Expand Down
Loading