diff --git a/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/engine/CorpusWorkFlowSuite.java b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/engine/CorpusWorkFlowSuite.java index 5d9d6878..0c313942 100644 --- a/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/engine/CorpusWorkFlowSuite.java +++ b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/engine/CorpusWorkFlowSuite.java @@ -59,10 +59,16 @@ public abstract class CorpusWorkFlowSuite { public static final String API_VALIDATE_NEGOTIATION_REJECT = "validateRejectPromptAndDataFilling"; public static final String API_VALIDATE_NEGOTIATION_ABORT = "validateAbortPromptAndDataFilling"; + public static final String API_GENERATE_NOTIFICATION_FROM_TEXT = "generateNotificationPromptFromText"; + public static final String API_GENERATE_NOTIFICATION_FROM_DATA = "generateNotificationPromptFromDataWithSchema"; + public static final String API_VALIDATE_NOTIFICATION = "validateNotificationPromptAndDataFilling"; + private static volatile SdkRuntimeAssembler.Runtime taskRuntimeSingleton; private static volatile SdkRuntimeAssembler.NegotiationRuntime negotiationRuntimeSingleton; + private static volatile SdkRuntimeAssembler.NotificationRuntime notificationRuntimeSingleton; + private final List results = new ArrayList<>(); private final Map scenarioDirs = new LinkedHashMap<>(); @@ -76,7 +82,7 @@ public abstract class CorpusWorkFlowSuite { /** Flow type used for the transcript and summary file names: {@code from_text} or {@code from_data}. */ protected abstract String flowType(); - /** Runtime kind: {@code "task"} (default) or {@code "negotiation"}. */ + /** Runtime kind: {@code "task"} (default), {@code "negotiation"} or {@code "notification"}. */ protected String runtimeKind() { return "task"; } @@ -90,6 +96,9 @@ Stream corpusCases() { if ("negotiation".equals(runtimeKind())) { SdkRuntimeAssembler.NegotiationRuntime rt = negotiationRuntime(); registry = SdkRuntimeAssembler.buildNegotiationRegistry(rt); + } else if ("notification".equals(runtimeKind())) { + SdkRuntimeAssembler.NotificationRuntime rt = notificationRuntime(); + registry = SdkRuntimeAssembler.buildNotificationRegistry(rt); } else { SdkRuntimeAssembler.Runtime rt = taskRuntime(); registry = SdkRuntimeAssembler.buildTaskRegistry(rt); @@ -151,10 +160,20 @@ private static synchronized SdkRuntimeAssembler.NegotiationRuntime negotiationRu return negotiationRuntimeSingleton; } + private static synchronized SdkRuntimeAssembler.NotificationRuntime notificationRuntime() { + if (notificationRuntimeSingleton == null) { + notificationRuntimeSingleton = SdkRuntimeAssembler.notificationRuntime(); + } + return notificationRuntimeSingleton; + } + private RecordingMeteredLlmClient registryRecorder() { if ("negotiation".equals(runtimeKind())) { return negotiationRuntime().recorder(); } + if ("notification".equals(runtimeKind())) { + return notificationRuntime().recorder(); + } return taskRuntime().recorder(); } @@ -188,4 +207,12 @@ public static Set negotiationApiNames() { API_VALIDATE_NEGOTIATION_REJECT, API_VALIDATE_NEGOTIATION_ABORT); } + + /** Notification-T phase-1 API names, used for load-time membership checks without touching the LLM runtime. */ + public static Set notificationApiNames() { + return Set.of( + API_GENERATE_NOTIFICATION_FROM_TEXT, + API_GENERATE_NOTIFICATION_FROM_DATA, + API_VALIDATE_NOTIFICATION); + } } \ No newline at end of file diff --git a/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/engine/registry/NotificationApis.java b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/engine/registry/NotificationApis.java new file mode 100644 index 00000000..fc3af0de --- /dev/null +++ b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/engine/registry/NotificationApis.java @@ -0,0 +1,33 @@ +package net.openan.a2at.sdk.corpus.engine.registry; + +import net.openan.a2at.sdk.client.prompt.orchestration.ClientPromptGenerationOrchestrator; +import net.openan.a2at.sdk.core.validation.ContentValidator; + +/** + * Notification-T API registration: JSON step arguments are bound to the production + * {@link ClientPromptGenerationOrchestrator} (from-text / from-data generation) and the Notification-T + * {@link ContentValidator} (validation) assembled by {@link SdkRuntimeAssembler}. + */ +public final class NotificationApis { + + private NotificationApis() {} + + public static void registerNotificationApis( + ApiRegistry registry, + ClientPromptGenerationOrchestrator client, + ContentValidator notificationValidator) { + registry.register("generateNotificationPromptFromText", args -> + ClientApis.metadataToMap(client.generateNotificationPromptFromText( + ClientApis.Args.text(args, "text"), ClientApis.Args.templateUri(args, "templateUri")))); + registry.register("generateNotificationPromptFromDataWithSchema", args -> + ClientApis.metadataToMap(client.generateNotificationPromptFromDataWithSchema( + ClientApis.Args.map(args, "data"), + ClientApis.Args.map(args, "schema"), + ClientApis.Args.templateUri(args, "templateUri")))); + registry.register("validateNotificationPromptAndDataFilling", args -> + ServerApis.filledToMap(notificationValidator.validate( + ClientApis.Args.text(args, "promptText"), + ClientApis.Args.map(args, "schema"), + ClientApis.Args.templateUri(args, "templateUri")))); + } +} \ No newline at end of file diff --git a/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/engine/registry/SdkRuntimeAssembler.java b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/engine/registry/SdkRuntimeAssembler.java index 92f6b868..280dce73 100644 --- a/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/engine/registry/SdkRuntimeAssembler.java +++ b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/engine/registry/SdkRuntimeAssembler.java @@ -39,6 +39,12 @@ public record NegotiationRuntime( RecordingMeteredLlmClient recorder, NegotiationGenerationOrchestrator orchestrator) {} + /** Fully assembled Notification-T runtime with the single shared recording LLM client. */ + public record NotificationRuntime( + RecordingMeteredLlmClient recorder, + ClientPromptGenerationOrchestrator clientGeneration, + ContentValidator notificationValidator) {} + private SdkRuntimeAssembler() {} private static RecordingMeteredLlmClient newRecorder(CorpusEnvConfig env) { @@ -122,4 +128,49 @@ public static ApiRegistry buildNegotiationRegistry(NegotiationRuntime runtime) { NegotiationApis.registerNegotiationApis(registry, runtime.orchestrator()); return registry; } + + public static NotificationRuntime notificationRuntime() { + CorpusEnvConfig env = CorpusEnvConfig.load(); + RecordingMeteredLlmClient recorder = newRecorder(env); + + LlmConfig llmConfig = new LlmConfig( + env.provider(), + env.model(), + env.apiKey(), + env.baseUrl(), + 10, + env.maxTokens(), + env.temperature(), + env.timeoutSeconds(), + 300, + 100, + false, + null, + env.maxAttempts(), + List.of()); + A2ATConfig config = new A2ATConfig( + new PromptRuntimeConfig("zh-CN", PromptRuntimeConfig.SOURCE_TYPE_CLASSPATH, null), + llmConfig, + new InputLimitConfig(InputLimitConfig.DEFAULT_MAX_TEXT_CHARS), + new NegotiationConfig("in_memory")); + + ClientPromptGenerationOrchestrator clientGeneration = DefaultA2ATClientBuilder.builder() + .config(config) + .envPath(env.envPath()) + .llmClient(recorder) + .buildPromptGenerationOrchestrator(); + ContentValidator notificationValidator = DefaultA2ATServerBuilder.builder() + .config(config) + .envPath(env.envPath()) + .llmClient(recorder) + .buildNotificationContentValidator(); + + return new NotificationRuntime(recorder, clientGeneration, notificationValidator); + } + + public static ApiRegistry buildNotificationRegistry(NotificationRuntime runtime) { + ApiRegistry registry = new ApiRegistry(); + NotificationApis.registerNotificationApis(registry, runtime.clientGeneration(), runtime.notificationValidator()); + return registry; + } } \ No newline at end of file diff --git a/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/NotificationSelfGuardTest.java b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/NotificationSelfGuardTest.java new file mode 100644 index 00000000..330b2252 --- /dev/null +++ b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/NotificationSelfGuardTest.java @@ -0,0 +1,63 @@ +package net.openan.a2at.sdk.corpus.suites.notification; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import net.openan.a2at.sdk.corpus.engine.CorpusWorkFlowSuite; +import net.openan.a2at.sdk.corpus.engine.discover.ScenarioScanner; +import net.openan.a2at.sdk.corpus.engine.loader.CaseFileLoader; +import net.openan.a2at.sdk.corpus.engine.loader.ExpectedStep; +import net.openan.a2at.sdk.corpus.engine.loader.InputCase; +import org.junit.jupiter.api.Test; + +/** + * Notification-T self-guard (meta test): validates every Notification-T scenario case file structurally without any + * LLM call - unknown keys, misaligned expectations, unknown api names, out-of-catalog error codes and + * category/expectation contradictions all fail here. + * + *

Id uniqueness is enforced per-file by the {@link CaseFileLoader}; ids may repeat across different flow files + * within the same scenario. + */ +public final class NotificationSelfGuardTest { + + /** Categories carrying a cross-step expectation contract (case data is Chinese). */ + static final String CATEGORY_NORMAL = "正常"; + + static final String CATEGORY_EXCEPTION = "异常"; + + @Test + void notificationScenarioCaseFilesAreStructurallyValid() { + List problems = new ArrayList<>(); + for (String flowFile : List.of( + CorpusWorkFlowSuite.INPUT_CASE_FROM_TEXT, CorpusWorkFlowSuite.INPUT_CASE_FROM_DATA)) { + for (ScenarioScanner.Scenario scenario : ScenarioScanner.discover("notification", flowFile)) { + List cases = new CaseFileLoader() + .load(scenario.inputFile(flowFile), CorpusWorkFlowSuite.notificationApiNames()); + for (InputCase inputCase : cases) { + checkCategoryContract(inputCase, problems); + } + } + } + assertTrue(problems.isEmpty(), "Notification corpus self-guard failures:\n- " + String.join("\n- ", problems)); + } + + private static void checkCategoryContract(InputCase inputCase, List problems) { + long errorExpected = 0; + for (ExpectedStep expectedStep : inputCase.expected()) { + if ("error".equals(expectedStep.result())) { + errorExpected++; + if (expectedStep.errCode().isBlank()) { + problems.add(inputCase.id() + ": error expectations must declare an errCode from the SDK error catalog"); + } + } + } + if (CATEGORY_EXCEPTION.equals(inputCase.caseCategory()) && errorExpected == 0) { + problems.add(inputCase.id() + ": categorized as " + CATEGORY_EXCEPTION + " but no step expects an error"); + } + if (CATEGORY_NORMAL.equals(inputCase.caseCategory()) && errorExpected > 0) { + problems.add(inputCase.id() + ": categorized as " + CATEGORY_NORMAL + " but a step expects an error; use " + + CATEGORY_EXCEPTION + " or \"boundary\""); + } + } +} \ No newline at end of file diff --git a/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/NotificationTFromDataWorkFlowTest.java b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/NotificationTFromDataWorkFlowTest.java new file mode 100644 index 00000000..997659e3 --- /dev/null +++ b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/NotificationTFromDataWorkFlowTest.java @@ -0,0 +1,42 @@ +package net.openan.a2at.sdk.corpus.suites.notification; + +import java.util.Set; +import net.openan.a2at.sdk.corpus.engine.CorpusWorkFlowSuite; + +/** + * Notification-T structured-input workflow suite: for every scenario directory under + * {@code suites/notification/resources/}, runs the recorded SDK API flow of each case in + * {@code input_case_from_data.json} against a real LLM. + * + *

Default API flow (also shown in the case files): {@code generateNotificationPromptFromDataWithSchema} → + * {@code validateNotificationPromptAndDataFilling}. + * + *

Filters: {@code -Dcorpus.scenario} and {@code -Dcase.filter}, see {@link NotificationTFromTextWorkFlowTest}. + */ +public final class NotificationTFromDataWorkFlowTest extends CorpusWorkFlowSuite { + + @Override + protected String extensionFolder() { + return "notification"; + } + + @Override + protected String inputFileName() { + return INPUT_CASE_FROM_DATA; + } + + @Override + protected String flowType() { + return FLOW_FROM_DATA; + } + + @Override + protected String runtimeKind() { + return "notification"; + } + + @Override + protected Set apiNames() { + return notificationApiNames(); + } +} \ No newline at end of file diff --git a/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/NotificationTFromTextWorkFlowTest.java b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/NotificationTFromTextWorkFlowTest.java new file mode 100644 index 00000000..af9d2391 --- /dev/null +++ b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/NotificationTFromTextWorkFlowTest.java @@ -0,0 +1,43 @@ +package net.openan.a2at.sdk.corpus.suites.notification; + +import java.util.Set; +import net.openan.a2at.sdk.corpus.engine.CorpusWorkFlowSuite; + +/** + * Notification-T natural-language workflow suite: for every scenario directory under + * {@code suites/notification/resources/}, runs the recorded SDK API flow of each case in + * {@code input_case_from_text.json} against a real LLM. + * + *

Default API flow (also shown in the case files): {@code generateNotificationPromptFromText} → + * {@code validateNotificationPromptAndDataFilling}. + * + *

Filters: {@code -Dcorpus.scenario=service-recovery} (glob, comma-separated) and + * {@code -Dcase.filter=TC00000001} (glob on case id). + */ +public final class NotificationTFromTextWorkFlowTest extends CorpusWorkFlowSuite { + + @Override + protected String extensionFolder() { + return "notification"; + } + + @Override + protected String inputFileName() { + return INPUT_CASE_FROM_TEXT; + } + + @Override + protected String flowType() { + return FLOW_FROM_TEXT; + } + + @Override + protected String runtimeKind() { + return "notification"; + } + + @Override + protected Set apiNames() { + return notificationApiNames(); + } +} \ No newline at end of file diff --git a/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/resources/service-recovery/input_case_from_data.json b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/resources/service-recovery/input_case_from_data.json new file mode 100644 index 00000000..4a3b3ac7 --- /dev/null +++ b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/resources/service-recovery/input_case_from_data.json @@ -0,0 +1,321 @@ +[ + { + "id": "TC00000001", + "caseDimension": "01-意图清晰参数完整", + "caseDesc": "data业务抢通事件-订阅条件(子网名称)+完整上报通知数据格式(7个必选字段)", + "caseCategory": "正常", + "input": [ + { + "api": "generateNotificationPromptFromDataWithSchema", + "args": { + "data": { + "condition": "子网名称:珠江新城子网", + "reportFormat": [ + { "name": "业务抢通方案执行状态", "values": ["未启动", "已结束"], "required": true }, + { "name": "投诉诊断任务流水号", "required": true }, + { "name": "OSS侧事件流水号", "required": true }, + { "name": "接入端口名称", "required": true }, + { "name": "是否已授权OMC自动抢通", "values": ["是", "否"], "required": true }, + { "name": "业务抢通方案名称", "required": true }, + { "name": "业务抢通方案详情", "required": true } + ] + }, + "schema": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "订阅条件,可选。待订阅的条件描述,例如:子网名称为xx子网。不带条件时留空。" + }, + "reportFormat": { + "type": "array", + "description": "上报通知数据格式,必选。描述所需上报内容的字段列表,每个字段包含信息项名称(必选)、取值范围(可选)、是否必选(可选)。", + "items": { + "type": "object", + "properties": { + "name": { "type": "string", "description": "信息项名称(必选)。" }, + "values": { "type": "array", "items": { "type": "string" }, "description": "取值范围(可选)。" }, + "required": { "type": "boolean", "description": "是否必选(可选)。" } + }, + "required": ["name"] + } + } + }, + "required": ["reportFormat"] + }, + "templateUri": "Notification-T/network-layer/service-recovery/v1" + } + }, + { + "api": "validateNotificationPromptAndDataFilling", + "args": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "订阅主题(必选)。订阅的事件主题名称,例如:业务抢通事件。" + }, + "subscriptionCondition": { + "type": "string", + "description": "订阅条件(可选)。待订阅的条件描述,例如:子网名称为xx子网。" + }, + "notificationDataFormat": { + "type": "string", + "description": "上报通知数据格式(必选)。待上报的通知数据格式描述,用于定义业务抢通事件的数据结构。" + } + }, + "required": ["topic", "notificationDataFormat"] + }, + "templateUri": "Notification-T/network-layer/service-recovery/v1", + "promptText": { + "$fromStep": 1, + "$field": "promptText" + } + } + } + ], + "expected": [ + { + "result": "success", + "data": {}, + "error": { "errCode": "", "errMessage": "" } + }, + { + "result": "success", + "data": { + "topic": "业务抢通事件", + "subscriptionCondition": "子网名称:珠江新城子网" + }, + "error": { "errCode": "", "errMessage": "" } + } + ] + }, + { + "id": "TC00000002", + "caseDimension": "01-意图清晰参数完整", + "caseDesc": "data业务抢通事件-仅上报通知数据格式(订阅条件可选缺省)", + "caseCategory": "正常", + "input": [ + { + "api": "generateNotificationPromptFromDataWithSchema", + "args": { + "data": { + "reportFormat": [ + { "name": "业务抢通方案执行状态", "values": ["未启动", "已结束"], "required": true }, + { "name": "投诉诊断任务流水号", "required": true }, + { "name": "OSS侧事件流水号", "required": true }, + { "name": "接入端口名称", "required": true }, + { "name": "是否已授权OMC自动抢通", "values": ["是", "否"], "required": true }, + { "name": "业务抢通方案名称", "required": true }, + { "name": "业务抢通方案详情", "required": true }, + { "name": "业务抢通方案执行结束时间", "required": false } + ] + }, + "schema": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "订阅条件,可选。待订阅的条件描述,例如:子网名称为xx子网。不带条件时留空。" + }, + "reportFormat": { + "type": "array", + "description": "上报通知数据格式,必选。描述所需上报内容的字段列表,每个字段包含信息项名称(必选)、取值范围(可选)、是否必选(可选)。", + "items": { + "type": "object", + "properties": { + "name": { "type": "string", "description": "信息项名称(必选)。" }, + "values": { "type": "array", "items": { "type": "string" }, "description": "取值范围(可选)。" }, + "required": { "type": "boolean", "description": "是否必选(可选)。" } + }, + "required": ["name"] + } + } + }, + "required": ["reportFormat"] + }, + "templateUri": "Notification-T/network-layer/service-recovery/v1" + } + }, + { + "api": "validateNotificationPromptAndDataFilling", + "args": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "订阅主题(必选)。订阅的事件主题名称,例如:业务抢通事件。" + }, + "subscriptionCondition": { + "type": "string", + "description": "订阅条件(可选)。待订阅的条件描述,例如:子网名称为xx子网。" + }, + "notificationDataFormat": { + "type": "string", + "description": "上报通知数据格式(必选)。待上报的通知数据格式描述,用于定义业务抢通事件的数据结构。" + } + }, + "required": ["topic", "notificationDataFormat"] + }, + "templateUri": "Notification-T/network-layer/service-recovery/v1", + "promptText": { + "$fromStep": 1, + "$field": "promptText" + } + } + } + ], + "expected": [ + { + "result": "success", + "data": {}, + "error": { "errCode": "", "errMessage": "" } + }, + { + "result": "success", + "data": { + "topic": "业务抢通事件" + }, + "error": { "errCode": "", "errMessage": "" } + } + ] + }, + { + "id": "TC00000003", + "caseDimension": "01-意图清晰参数完整", + "caseDesc": "data业务抢通事件-精简上报通知数据格式(4个字段)", + "caseCategory": "正常", + "input": [ + { + "api": "generateNotificationPromptFromDataWithSchema", + "args": { + "data": { + "condition": "子网名称:珠江新城子网", + "reportFormat": [ + { "name": "业务抢通方案执行状态", "values": ["未启动", "已结束"], "required": true }, + { "name": "投诉诊断任务流水号", "required": true }, + { "name": "接入端口名称", "required": true }, + { "name": "业务抢通方案名称", "required": true } + ] + }, + "schema": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "订阅条件,可选。待订阅的条件描述,例如:子网名称为xx子网。不带条件时留空。" + }, + "reportFormat": { + "type": "array", + "description": "上报通知数据格式,必选。描述所需上报内容的字段列表,每个字段包含信息项名称(必选)、取值范围(可选)、是否必选(可选)。", + "items": { + "type": "object", + "properties": { + "name": { "type": "string", "description": "信息项名称(必选)。" }, + "values": { "type": "array", "items": { "type": "string" }, "description": "取值范围(可选)。" }, + "required": { "type": "boolean", "description": "是否必选(可选)。" } + }, + "required": ["name"] + } + } + }, + "required": ["reportFormat"] + }, + "templateUri": "Notification-T/network-layer/service-recovery/v1" + } + }, + { + "api": "validateNotificationPromptAndDataFilling", + "args": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "订阅主题(必选)。订阅的事件主题名称,例如:业务抢通事件。" + }, + "subscriptionCondition": { + "type": "string", + "description": "订阅条件(可选)。待订阅的条件描述,例如:子网名称为xx子网。" + }, + "notificationDataFormat": { + "type": "string", + "description": "上报通知数据格式(必选)。待上报的通知数据格式描述,用于定义业务抢通事件的数据结构。" + } + }, + "required": ["topic", "notificationDataFormat"] + }, + "templateUri": "Notification-T/network-layer/service-recovery/v1", + "promptText": { + "$fromStep": 1, + "$field": "promptText" + } + } + } + ], + "expected": [ + { + "result": "success", + "data": {}, + "error": { "errCode": "", "errMessage": "" } + }, + { + "result": "success", + "data": { + "topic": "业务抢通事件", + "subscriptionCondition": "子网名称:珠江新城子网" + }, + "error": { "errCode": "", "errMessage": "" } + } + ] + }, + { + "id": "TC00000004", + "caseDimension": "04-关键信息缺失", + "caseDesc": "data业务抢通事件-缺少必选的上报通知数据格式", + "caseCategory": "异常", + "input": [ + { + "api": "generateNotificationPromptFromDataWithSchema", + "args": { + "data": { + "condition": "子网名称:珠江新城子网" + }, + "schema": { + "type": "object", + "properties": { + "condition": { + "type": "string", + "description": "订阅条件,可选。待订阅的条件描述,例如:子网名称为xx子网。不带条件时留空。" + }, + "reportFormat": { + "type": "array", + "description": "上报通知数据格式,必选。描述所需上报内容的字段列表,每个字段包含信息项名称(必选)、取值范围(可选)、是否必选(可选)。", + "items": { + "type": "object", + "properties": { + "name": { "type": "string", "description": "信息项名称(必选)。" }, + "values": { "type": "array", "items": { "type": "string" }, "description": "取值范围(可选)。" }, + "required": { "type": "boolean", "description": "是否必选(可选)。" } + }, + "required": ["name"] + } + } + }, + "required": ["reportFormat"] + }, + "templateUri": "Notification-T/network-layer/service-recovery/v1" + } + } + ], + "expected": [ + { + "result": "error", + "data": {}, + "error": { "errCode": "slot.not_provided", "errMessage": "" } + } + ] + } +] diff --git a/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/resources/service-recovery/input_case_from_text.json b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/resources/service-recovery/input_case_from_text.json new file mode 100644 index 00000000..e130d13b --- /dev/null +++ b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/resources/service-recovery/input_case_from_text.json @@ -0,0 +1,199 @@ +[ + { + "id": "TC00000001", + "caseDimension": "01-意图清晰参数完整", + "caseDesc": "业务抢通事件-订阅条件(子网名称)+完整上报通知数据格式(7个必选字段)", + "caseCategory": "正常", + "input": [ + { + "api": "generateNotificationPromptFromText", + "args": { + "text": "我想订阅业务抢通事件,订阅条件为子网名称为珠江新城子网。上报通知数据格式如下:1. 业务抢通方案执行状态,取值范围:未启动、已结束;2. 投诉诊断任务流水号;3. OSS侧事件流水号;4. 接入端口名称;5. 是否已授权OMC自动抢通,取值范围:是、否;6. 业务抢通方案名称;7. 业务抢通方案详情。", + "templateUri": "Notification-T/network-layer/service-recovery/v1" + } + }, + { + "api": "validateNotificationPromptAndDataFilling", + "args": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "订阅主题(必选)。订阅的事件主题名称,例如:业务抢通事件。" + }, + "subscriptionCondition": { + "type": "string", + "description": "订阅条件(可选)。待订阅的条件描述,例如:子网名称为xx子网。" + }, + "notificationDataFormat": { + "type": "string", + "description": "上报通知数据格式(必选)。待上报的通知数据格式描述,用于定义业务抢通事件的数据结构。" + } + }, + "required": ["topic", "notificationDataFormat"] + }, + "templateUri": "Notification-T/network-layer/service-recovery/v1", + "promptText": { + "$fromStep": 1, + "$field": "promptText" + } + } + } + ], + "expected": [ + { + "result": "success", + "data": {}, + "error": { "errCode": "", "errMessage": "" } + }, + { + "result": "success", + "data": { + "topic": "业务抢通事件", + "subscriptionCondition": "子网名称:珠江新城子网", + "notificationDataFormat": "业务抢通事件数据包含:业务抢通方案执行状态(未启动、已结束)、投诉诊断任务流水号、OSS侧事件流水号、接入端口名称、是否已授权OMC自动抢通(是、否)、业务抢通方案名称、业务抢通方案详情。" + }, + "error": { "errCode": "", "errMessage": "" } + } + ] + }, + { + "id": "TC00000002", + "caseDimension": "01-意图清晰参数完整", + "caseDesc": "业务抢通事件-无订阅条件(可选缺省)+完整上报通知数据格式", + "caseCategory": "正常", + "input": [ + { + "api": "generateNotificationPromptFromText", + "args": { + "text": "我想订阅业务抢通事件。上报通知数据格式如下:1. 业务抢通方案执行状态,取值范围:未启动、已结束;2. 投诉诊断任务流水号;3. OSS侧事件流水号;4. 接入端口名称;5. 是否已授权OMC自动抢通,取值范围:是、否;6. 业务抢通方案名称;7. 业务抢通方案详情。", + "templateUri": "Notification-T/network-layer/service-recovery/v1" + } + }, + { + "api": "validateNotificationPromptAndDataFilling", + "args": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "订阅主题(必选)。订阅的事件主题名称,例如:业务抢通事件。" + }, + "subscriptionCondition": { + "type": "string", + "description": "订阅条件(可选)。待订阅的条件描述,例如:子网名称为xx子网。" + }, + "notificationDataFormat": { + "type": "string", + "description": "上报通知数据格式(必选)。待上报的通知数据格式描述,用于定义业务抢通事件的数据结构。" + } + }, + "required": ["topic", "notificationDataFormat"] + }, + "templateUri": "Notification-T/network-layer/service-recovery/v1", + "promptText": { + "$fromStep": 1, + "$field": "promptText" + } + } + } + ], + "expected": [ + { + "result": "success", + "data": {}, + "error": { "errCode": "", "errMessage": "" } + }, + { + "result": "success", + "data": { + "topic": "业务抢通事件", + "notificationDataFormat": "业务抢通事件数据包含:业务抢通方案执行状态(未启动、已结束)、投诉诊断任务流水号、OSS侧事件流水号、接入端口名称、是否已授权OMC自动抢通(是、否)、业务抢通方案名称、业务抢通方案详情。" + }, + "error": { "errCode": "", "errMessage": "" } + } + ] + }, + { + "id": "TC00000003", + "caseDimension": "01-意图清晰参数完整", + "caseDesc": "业务抢通事件-订阅条件(子网名称)+精简上报通知数据格式(4个字段)", + "caseCategory": "正常", + "input": [ + { + "api": "generateNotificationPromptFromText", + "args": { + "text": "我想订阅业务抢通事件,订阅条件为子网名称为珠江新城子网。上报通知数据格式如下:1. 业务抢通方案执行状态,取值范围:未启动、已结束;2. 投诉诊断任务流水号;3. 接入端口名称;4. 业务抢通方案名称。", + "templateUri": "Notification-T/network-layer/service-recovery/v1" + } + }, + { + "api": "validateNotificationPromptAndDataFilling", + "args": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "订阅主题(必选)。订阅的事件主题名称,例如:业务抢通事件。" + }, + "subscriptionCondition": { + "type": "string", + "description": "订阅条件(可选)。待订阅的条件描述,例如:子网名称为xx子网。" + }, + "notificationDataFormat": { + "type": "string", + "description": "上报通知数据格式(必选)。待上报的通知数据格式描述,用于定义业务抢通事件的数据结构。" + } + }, + "required": ["topic", "notificationDataFormat"] + }, + "templateUri": "Notification-T/network-layer/service-recovery/v1", + "promptText": { + "$fromStep": 1, + "$field": "promptText" + } + } + } + ], + "expected": [ + { + "result": "success", + "data": {}, + "error": { "errCode": "", "errMessage": "" } + }, + { + "result": "success", + "data": { + "topic": "业务抢通事件", + "subscriptionCondition": "子网名称:珠江新城子网" + }, + "error": { "errCode": "", "errMessage": "" } + } + ] + }, + { + "id": "TC00000004", + "caseDimension": "04-关键信息缺失", + "caseDesc": "业务抢通事件-缺少必选的上报通知数据格式", + "caseCategory": "异常", + "input": [ + { + "api": "generateNotificationPromptFromText", + "args": { + "text": "我想订阅业务抢通事件,订阅条件为子网名称为珠江新城子网。", + "templateUri": "Notification-T/network-layer/service-recovery/v1" + } + } + ], + "expected": [ + { + "result": "error", + "data": {}, + "error": { "errCode": "slot.not_provided", "errMessage": "" } + } + ] + } +] diff --git a/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/resources/subscribe-incident/input_case_from_data.json b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/resources/subscribe-incident/input_case_from_data.json new file mode 100644 index 00000000..e272b91d --- /dev/null +++ b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/resources/subscribe-incident/input_case_from_data.json @@ -0,0 +1,240 @@ +[ + { + "id": "TC00000001", + "caseDimension": "01-意图清晰参数完整", + "caseDesc": "data Incident订阅-通知主题+订阅条件+DataPart承载", + "caseCategory": "正常", + "input": [ + { + "api": "generateNotificationPromptFromDataWithSchema", + "args": { + "data": { + "topic": "Incident", + "condition": "故障优先级为严重、高,故障名称为光纤中断、单板故障", + "dataFormat": "通过DataPart上报Incident数据" + }, + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "通知主题(必填)。待订阅的事件主题名称,如 Incident、Fault、智能故障、故障。" + }, + "condition": { + "type": "string", + "description": "订阅条件(可选)。待订阅的条件描述,可包含故障优先级与故障名称。" + }, + "dataFormat": { + "type": "string", + "description": "上报通知数据格式(可选)。待上报的数据类型与承载 Part,如 DataPart、TextPart。" + } + }, + "required": ["topic"] + }, + "templateUri": "Notification-T/network-layer/subscribe-incident/v1" + } + }, + { + "api": "validateNotificationPromptAndDataFilling", + "args": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "订阅主题(必填)。要订阅的事件主题名称。" + }, + "subscriptionCondition": { + "type": "string", + "description": "订阅条件(可选)。要订阅的条件的描述。" + }, + "notificationDataFormat": { + "type": "string", + "description": "上报通知数据格式(必填)。要上报的通知数据格式的描述。" + } + }, + "required": ["topic", "notificationDataFormat"] + }, + "templateUri": "Notification-T/network-layer/subscribe-incident/v1", + "promptText": { + "$fromStep": 1, + "$field": "promptText" + } + } + } + ], + "expected": [ + { + "result": "success", + "data": {}, + "error": { "errCode": "", "errMessage": "" } + }, + { + "result": "success", + "data": { + "topic": "Incident", + "subscriptionCondition": "故障优先级为严重、高,故障名称为光纤中断、单板故障" + }, + "error": { "errCode": "", "errMessage": "" } + } + ] + }, + { + "id": "TC00000002", + "caseDimension": "01-意图清晰参数完整", + "caseDesc": "data Fault订阅-英文优先级语义+光模块故障+DataPart承载", + "caseCategory": "正常", + "input": [ + { + "api": "generateNotificationPromptFromDataWithSchema", + "args": { + "data": { + "topic": "Fault", + "condition": "故障优先级为critical、high,故障名称为光纤中断、光模块故障", + "dataFormat": "通过DataPart上报故障数据" + }, + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "通知主题(必填)。待订阅的事件主题名称,如 Incident、Fault、智能故障、故障。" + }, + "condition": { + "type": "string", + "description": "订阅条件(可选)。待订阅的条件描述,可包含故障优先级与故障名称。" + }, + "dataFormat": { + "type": "string", + "description": "上报通知数据格式(可选)。待上报的数据类型与承载 Part,如 DataPart、TextPart。" + } + }, + "required": ["topic"] + }, + "templateUri": "Notification-T/network-layer/subscribe-incident/v1" + } + }, + { + "api": "validateNotificationPromptAndDataFilling", + "args": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "订阅主题(必填)。要订阅的事件主题名称。" + }, + "subscriptionCondition": { + "type": "string", + "description": "订阅条件(可选)。要订阅的条件的描述。" + }, + "notificationDataFormat": { + "type": "string", + "description": "上报通知数据格式(必填)。要上报的通知数据格式的描述。" + } + }, + "required": ["topic", "notificationDataFormat"] + }, + "templateUri": "Notification-T/network-layer/subscribe-incident/v1", + "promptText": { + "$fromStep": 1, + "$field": "promptText" + } + } + } + ], + "expected": [ + { + "result": "success", + "data": {}, + "error": { "errCode": "", "errMessage": "" } + }, + { + "result": "success", + "data": { + "topic": "Fault", + "subscriptionCondition": "故障优先级为critical、high,故障名称为光纤中断、光模块故障" + }, + "error": { "errCode": "", "errMessage": "" } + } + ] + }, + { + "id": "TC00000003", + "caseDimension": "05-可选参数缺省", + "caseDesc": "data 智能故障订阅-通知主题(中文)+无订阅条件+TextPart承载", + "caseCategory": "边界", + "input": [ + { + "api": "generateNotificationPromptFromDataWithSchema", + "args": { + "data": { + "topic": "智能故障", + "dataFormat": "通过TextPart上报故障数据" + }, + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "通知主题(必填)。待订阅的事件主题名称,如 Incident、Fault、智能故障、故障。" + }, + "condition": { + "type": "string", + "description": "订阅条件(可选)。待订阅的条件描述,可包含故障优先级与故障名称。" + }, + "dataFormat": { + "type": "string", + "description": "上报通知数据格式(可选)。待上报的数据类型与承载 Part,如 DataPart、TextPart。" + } + }, + "required": ["topic"] + }, + "templateUri": "Notification-T/network-layer/subscribe-incident/v1" + } + }, + { + "api": "validateNotificationPromptAndDataFilling", + "args": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "订阅主题(必填)。要订阅的事件主题名称。" + }, + "subscriptionCondition": { + "type": "string", + "description": "订阅条件(可选)。要订阅的条件的描述。" + }, + "notificationDataFormat": { + "type": "string", + "description": "上报通知数据格式(必填)。要上报的通知数据格式的描述。" + } + }, + "required": ["topic", "notificationDataFormat"] + }, + "templateUri": "Notification-T/network-layer/subscribe-incident/v1", + "promptText": { + "$fromStep": 1, + "$field": "promptText" + } + } + } + ], + "expected": [ + { + "result": "success", + "data": {}, + "error": { "errCode": "", "errMessage": "" } + }, + { + "result": "success", + "data": { + "topic": "智能故障" + }, + "error": { "errCode": "", "errMessage": "" } + } + ] + } +] \ No newline at end of file diff --git a/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/resources/subscribe-incident/input_case_from_text.json b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/resources/subscribe-incident/input_case_from_text.json new file mode 100644 index 00000000..010854c8 --- /dev/null +++ b/a2a-t-corpus/src/test/java/net/openan/a2at/sdk/corpus/suites/notification/resources/subscribe-incident/input_case_from_text.json @@ -0,0 +1,176 @@ +[ + { + "id": "TC00000001", + "caseDimension": "01-意图清晰参数完整", + "caseDesc": "Incident订阅-通知主题+订阅条件(优先级与故障名称)+DataPart承载", + "caseCategory": "正常", + "input": [ + { + "api": "generateNotificationPromptFromText", + "args": { + "text": "请生成一个智能故障Incident订阅任务:通知主题为Incident,订阅条件为故障优先级为严重、高,故障名称为光纤中断、单板故障,上报通知数据格式为通过DataPart上报Incident数据", + "templateUri": "Notification-T/network-layer/subscribe-incident/v1" + } + }, + { + "api": "validateNotificationPromptAndDataFilling", + "args": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "订阅主题(必填)。要订阅的事件主题名称。" + }, + "subscriptionCondition": { + "type": "string", + "description": "订阅条件(可选)。要订阅的条件的描述。" + }, + "notificationDataFormat": { + "type": "string", + "description": "上报通知数据格式(必填)。要上报的通知数据格式的描述。" + } + }, + "required": ["topic", "notificationDataFormat"] + }, + "templateUri": "Notification-T/network-layer/subscribe-incident/v1", + "promptText": { + "$fromStep": 1, + "$field": "promptText" + } + } + } + ], + "expected": [ + { + "result": "success", + "data": {}, + "error": { "errCode": "", "errMessage": "" } + }, + { + "result": "success", + "data": { + "topic": "Incident", + "subscriptionCondition": "故障优先级为严重、高,故障名称为光纤中断、单板故障", + "notificationDataFormat": "通过DataPart上报Incident数据" + }, + "error": { "errCode": "", "errMessage": "" } + } + ] + }, + { + "id": "TC00000002", + "caseDimension": "01-意图清晰参数完整", + "caseDesc": "Fault订阅-英文优先级语义(critical、high)+DataPart承载", + "caseCategory": "正常", + "input": [ + { + "api": "generateNotificationPromptFromText", + "args": { + "text": "请生成一个智能故障订阅任务:通知主题为Fault,订阅条件为故障优先级为critical、high,故障名称为光纤中断、光模块故障,上报通知数据格式为通过DataPart上报故障数据", + "templateUri": "Notification-T/network-layer/subscribe-incident/v1" + } + }, + { + "api": "validateNotificationPromptAndDataFilling", + "args": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "订阅主题(必填)。要订阅的事件主题名称。" + }, + "subscriptionCondition": { + "type": "string", + "description": "订阅条件(可选)。要订阅的条件的描述。" + }, + "notificationDataFormat": { + "type": "string", + "description": "上报通知数据格式(必填)。要上报的通知数据格式的描述。" + } + }, + "required": ["topic", "notificationDataFormat"] + }, + "templateUri": "Notification-T/network-layer/subscribe-incident/v1", + "promptText": { + "$fromStep": 1, + "$field": "promptText" + } + } + } + ], + "expected": [ + { + "result": "success", + "data": {}, + "error": { "errCode": "", "errMessage": "" } + }, + { + "result": "success", + "data": { + "topic": "Fault", + "subscriptionCondition": "故障优先级为critical、high,故障名称为光纤中断、光模块故障" + }, + "error": { "errCode": "", "errMessage": "" } + } + ] + }, + { + "id": "TC00000003", + "caseDimension": "05-可选参数缺省", + "caseDesc": "智能故障订阅-通知主题(中文)+无订阅条件(可选缺省)+TextPart承载", + "caseCategory": "边界", + "input": [ + { + "api": "generateNotificationPromptFromText", + "args": { + "text": "请生成一个智能故障订阅任务:通知主题为智能故障,上报通知数据格式为通过TextPart上报故障数据", + "templateUri": "Notification-T/network-layer/subscribe-incident/v1" + } + }, + { + "api": "validateNotificationPromptAndDataFilling", + "args": { + "schema": { + "type": "object", + "properties": { + "topic": { + "type": "string", + "description": "订阅主题(必填)。要订阅的事件主题名称。" + }, + "subscriptionCondition": { + "type": "string", + "description": "订阅条件(可选)。要订阅的条件的描述。" + }, + "notificationDataFormat": { + "type": "string", + "description": "上报通知数据格式(必填)。要上报的通知数据格式的描述。" + } + }, + "required": ["topic", "notificationDataFormat"] + }, + "templateUri": "Notification-T/network-layer/subscribe-incident/v1", + "promptText": { + "$fromStep": 1, + "$field": "promptText" + } + } + } + ], + "expected": [ + { + "result": "success", + "data": {}, + "error": { "errCode": "", "errMessage": "" } + }, + { + "result": "success", + "data": { + "topic": "智能故障" + }, + "error": { "errCode": "", "errMessage": "" } + } + ] + } +]