Repository navigation
feat(core): unify error codes and messages on a bilingual error catalog - #1
Open
codetalks-hw wants to merge 242 commits into
Open
codetalks-hw wants to merge 242 commits into
codetalks-hw wants to merge 242 commits into
Conversation
build(pom): add Error Prone, NullAway and JSpecify to build
…le code Move the error code contract to the A2ATError root (getCode() never null, default sdk_internal_error) and delete SdkException; re-parent ConfigFileNotFoundException / ResourceNotFoundException / PromptGenerationException / ContentValidationException onto A2ATError, retype OperationResult.error to A2ATError, and convert ValidationPipeline argument checks to NPE/IllegalArgumentException. Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
LLMError now extends A2ATError so LLMConfigError/LLMRuntimeError join the unified processing-failure tree; ClasspathPromptResourceLoader I/O wraps use A2ATError. Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
ScenarioRecognitionException / TaskPromptRenderException extend A2ATError; loader and validator I/O wraps use A2ATError; TaskPromptRenderer null template becomes Objects.requireNonNull (outside the tree). Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
… NPE/IAE All ~45 argument-contract throw sites now use Objects.requireNonNull for null and IllegalArgumentException for blank/malformed/semantic violations, staying outside the A2ATError tree; NegotiationReference.parse becomes tryParse returning Optional (removing catch-based control flow); NegotiationProcessingException delegates its code to the A2ATError root; observability boundary tests rewritten against the new carriers. Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
Client orchestrator catches a single A2ATError (LLMRuntimeError and config errors now converge into result failures); PromptComplianceCheckException extends A2ATError keeping stage; blank/malformed template URIs on facade entry surface as NPE/IllegalArgumentException per the boundary contract; facade @throws javadoc updated. Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
Document the single A2ATError root with machine-readable code, the NPE/IllegalArgumentException boundary for programming errors, tryParse, and the removed SdkException/NegotiationContentException; both languages in sync. Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…tion-unification Refactor/exception unification
Signed-off-by: w00609601 <wushunhao1@huawei.com>
…dation refactor: rename template_uri metadata key to templateUri
- TemplateUri: structured always-valid template identifier composed of extensionName, version and trailing segments; of() validates segments, parse() mirrors NegotiationReference.tryParse semantics, withLanguage() binds runtime language into a TemplateReference - StandardTemplates: 11 built-in template constants in the spirit of java.nio.charset.StandardCharsets, with TASK/NOTIFICATION/AUTHORIZATION/ NEGOTIATION group views - TemplateReference: rename extensionPrefix() to extensionName() and move SimpleTemplateReference from DefaultContentValidator into core - lock constants to bundled resource tree (a2a-t-resources) and to NegotiationReference composition (a2a-t-negotiation) via consistency tests Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…prone compatibility The old_jdk_support profile lowers error-prone to 2.42.0 + nullaway 0.12.10 for older JDKs, but its activation boundary (17, 21] excluded JDK 17 itself. As a result JDK 17 fell back to the default error-prone 2.50.0, whose class files target Java 21 (version 65), so javac failed to load the annotation processor via ServiceLoader (ClassLoader.defineClass1). Switch the boundary to the closed interval [17, 21] so JDK 17 activates the downgrade and installs cleanly. Signed-off-by: ZhouJie6 <ivo.zhou@huawei.com>
fix(profile): include JDK 17 in old_jdk_support activation for error-prone compatibility
…ndardTemplates - main code: DefaultA2ATServerBuilder validator prefixes, loader KNOWN_TEMPLATE_TYPES/KNOWN_SLOT_TYPES lists and NegotiationReference URI_PREFIX now derive from StandardTemplates *_EXTENSION_NAME constants (probe order preserved); core is the single source of extension names - tests: ~90 hardcoded builtin template URI literals across a2a-t-client, a2a-t-server, a2a-t-negotiation, a2a-t-prompt, a2a-t-core and a2a-t-sample replaced with StandardTemplates.XXX.uri() references; local *_URI test constants keep their names, only initializers swapped - negative/malformed URI fixtures, non-builtin fixture URIs and compositional URI constructions intentionally left as raw strings - javadoc value-documentation literals kept raw (they describe what the value is, not how to use it) Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…dard-template-uri Refactor/standard template uri
…peline over TemplateUri Analysis showed the TemplateReference interface carried no weight: no caller ever read language() through the interface (language flows from global prompt config each validator already holds), and its remaining surface (uri + extensionName) is exactly TemplateUri. The instanceof escape hatch in NegotiationSemanticValidator existed only because the interface could not express negotiation-specific data. - delete TemplateReference, SimpleTemplateReference and TemplateUri.withLanguage()/extensionPrefix(); language is runtime config, never an addressability dimension of the template - genericize core pipeline: SemanticValidator<T> and ValidationPipeline<T> - prompt module: ValidationPipeline<TemplateUri>, DefaultSemanticValidator implements SemanticValidator<TemplateUri>, DefaultContentValidator builds a TemplateUri after its structural checks - negotiation module: ValidationPipeline<NegotiationReference>, NegotiationSemanticValidator extends SemanticValidator<NegotiationReference> with the negotiation-specific method renamed to validateNegotiation; the instanceof/cast default adapter is gone - NegotiationReference is a plain record again, its uncalled extensionName() override removed Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…dard-template-uri refactor(validation): remove TemplateReference in favor of generic pipeline over TemplateUri
…h trailing version
Internal review decision: drop the extension version segment, keep a
trailing template version (default v1) and insert a network-layer domain
segment into the Task-T and Notification-T paths. The URI now mirrors
the resource directory one-to-one and the Authorization-T scenario is
renamed to authorization-policy-management.
New layout:
- Task-T/network-layer/<scenario>/v1
- Notification-T/network-layer/<scenario>/v1
- Authorization-T/authorization-policy-management/v1
- Negotiation-T/<type>/<phase>/v1
- TemplateUri record is now {extensionName, pathSegments, templateVersion}
with TemplateUri.DEFAULT_TEMPLATE_VERSION and a parse() that expects
>= 3 segments (extension + >= 1 path segment + trailing version)
- StandardTemplates constants updated, AUTHZ_POLICY_MGR renamed to
AUTHORIZATION_POLICY_MANAGEMENT, new NETWORK_LAYER_SEGMENT constant
- bundled templates/slots trees git-mv'd to mirror the new URIs; the
template lint gate rules follow the new layouts
- NegotiationReference composes and parses the new 4-segment negotiation
URIs; DefaultNegotiationTemplateLoader paths updated
- PromptResourceKey redesigned around path segments with template()/
slotSchema()/scenario() factories taking TemplateUri; classpath and
local-file loaders resolve full URIs directly and probe bare scenario
codes against both the network-layer and plain layouts
- DefaultContentValidator validates first (extension name) and last
(template version) segments
- tests, test fixture trees and bilingual docs migrated to the new layout
Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…dard-template-uri refactor(templates): reshape template URI layout to path-segments with trailing version
…cade chain and add JSpecify nullness annotations Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
… to core.model, NegotiationContentService to generation, flatten taskrendering.api Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…asses to package-private visibility Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…lateUri.of version Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…idate duplicate value types and align nullness contracts Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…ateUri value type Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…s single source of truth Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…dard-template-uri refactor(api): replace String templateUri with TemplateUri type on fa…
…ing with the template regime Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…dard-template-uri refactor: tighten internal structure, naming and error-code surface across modules
…dard-template-uri-2 refactor/standard-template-uri-2 — Typed PromptTemplate URI + file-driven negotiation vocabulary
…ion-confirm-request feat(negotiation): add confirm-request rounds to target and feasibility propose
Signed-off-by: gcw_mr3RVhmf <cnafan@outlook.com>
Signed-off-by: gcw_mr3RVhmf <cnafan@outlook.com>
…normal-github-pr test(sample): add negotiation abnormal evaluations
…mple-run-guide docs(sample): document negotiation evaluation runs
Align the propose cases with the request semantics of a propose message:
items carry the field expectation as a meaning-plus-sample description
("接入端口名称,如P781-..."), per the propose template's own requirement
(name + meaning/format/sample) - not the field's real value, which read as
"asking for the answer while carrying it". Accept keeps real values,
reject keeps field-plus-reason; all three message types now carry exactly
what the protocol transports.
The propose extraction assertions are sharpened against the
description-vs-value confusion: the extracted expectation must keep the
meaning head (a sample-only extraction would read as if the field were
already supplied) and must stay within the stated expectation (no
hallucinated content). Depends on the propose-branch extraction contract
in the stacked SDK change.
Signed-off-by: ZhouJie6 <ivo.zhou@huawei.com>
…k object
Review feedback on the propose cases:
- the task-object expectation now presents the three selectable forms the
Task-T template defines (service name / service identifier / access
port name, each with its sample) instead of the access-port form alone;
the accept cases rotate the filled task object across the three forms
so every legal shape round-trips
- the extraction schema mirrors the SDK's own model of the message
content (NegotiationJsonSchemaBuilder) instead of an invented flat
field map: propose extracts {items: [{name, value}], relationship},
endings extract {conclusion, items: [{name, value}]} - the
validation-side contract is now aligned end to end with the
generation-side model. The assertions walk the items array: every input
slot appears as an item with the matching value (expectation guards for
propose, value fidelity for accept, reasons for reject), plus the
relationship and conclusion checks.
Verified on glm-5.2: 14/14 on the first and a confirmation rerun; one
intermittent run failed a single case on an LLM infrastructure error
(model returned markdown-fenced JSON) - transient, not a case defect.
Signed-off-by: ZhouJie6 <ivo.zhou@huawei.com>
…proposes A single requested field has no inter-field relationship, so the rendered propose must not carry the canned relationship sentence: the eval app and the server executor now pass a null relationship when only one item is missing, and the phrasing template states the AND relation explicitly. Signed-off-by: ZhouJie6 <ivo.zhou@huawei.com>
The generation-only fromData/fromText 3x3 samples printed summaries without assertions and are fully covered by the stronger evaluators: NegotiationFromDataApiEvalApp (fromData generate-validate round trip) and NegotiationEvalApp plus the private-line corpus evaluation (fromText with golden comparison). Removes the samples, their shared support class, the now-orphaned ScenarioData case accessors, the negotiation_cases scenario section, the javaargs generation blocks, and the corresponding README/design-doc sections. Also aligns the scenario field model with the Task-T template vocabulary. Signed-off-by: ZhouJie6 <ivo.zhou@huawei.com>
…orpus on both channels
InformationNegotiationSchemas moves from the private-line sample to the
shared negotiation package: the validate*AndDataFilling contracts are
channel-agnostic, so the fromText flows and the fromData evaluator now
use one schema (items:[{name, requirement|value|reason}]). The fromData
API evaluator delegates to the shared schemas and additionally asserts
the extracted accept values and reject reasons.
The labelled corpus (cases.json) gains a structured data field parallel
to each text input and switches expected keys to the display names, so
one corpus drives both generation channels. The corpus evaluation runs
the protocol-correct chain: the server proposes, the client validates
the inbound propose and discovers the fields to supplement, the client
generates the accept/reject from that discovery, and the server
validates the ending. The fromData channel additionally requires an
exact completedPrompt match because its rendering is deterministic.
Fixes the expected-value matching that silently always failed since the
schema moved to the item-array shape.
Signed-off-by: ZhouJie6 <ivo.zhou@huawei.com>
…raction-contract fix(negotiation): define the propose-branch extraction contract as full expectation text
…eneration Terse corpus ending texts may omit or paraphrase the field names, so the LLM extraction could not recover the requested items (three smoke cases failed with extraction errors and most ending extractions missed). The fromText ending input now leads with an explicit supplement built from the fields the client discovered in the inbound propose, mirroring NegotiationEvalApp step 6. Signed-off-by: ZhouJie6 <ivo.zhou@huawei.com>
…se-expectation feat(sample): unify negotiation validation schemas and evaluate the corpus on both channels
The content validation prompt now draws a division of labor between validation sources: the template body carries business rules (per-operation-type required fields, modifiability, operation scope) while the parameter schema carries value and format constraints. The schema's field set and descriptive statements no longer participate in judging field existence or required-ness - a field missing from the schema does not exempt the template's requirement, and a schema description contradicting a template required field does not alter it. Format compliance is decided by the schema's declaration when it disagrees with the template's shape description for the same field, so declared format tightenings (single date, ISO timestamp) now reject mismatched range values. The format_error definition gains inverted date ranges, the key-set contract requires schema key names for empty values, and the format-compliance example avoids literal date patterns. The suite grows to 102 cases. Four varreq variants flip from success to rejected pairs (format tightening beats template range wording), b3-conflict pair input moves the conflicting dual value onto the modifiable validity period (the scene variant collided with the modifiability rule and double-triggered), a-nl-neg-03 becomes a two-stage expectation (client renders faithfully, server rejects the identifier-less delete), the c4 varfields schema drops its stale conditional-delete description, and two new cases join: a description-antagonist variant (schema text says condition delete is fine, template still wins) and a multi-error case covering the previously untested multi-slot_errors path. LoaderTest counts follow (102 total, 47 variants including the -varuuid/-vardesc suffixes, 9 interceptions, 37 rejections, 43 validate_schemas). Template lint and the sample test suite pass; smoke passes 15/15 and the transcript is regenerated. Full-suite runs after the model change sit at 98-99/102 with residual mismatches attributed to LLM non-determinism (error-code wobble on one variant) and transient gateway JSON failures. Signed-off-by: w00609601 <wushunhao1@huawei.com>
…xtend feat(sample): split validation and extraction sources in authz suite
…routing and frozen snapshots Signed-off-by: w00609601 <wushunhao1@huawei.com>
…iss warning Signed-off-by: w00609601 <wushunhao1@huawei.com>
…th fail-fast Signed-off-by: w00609601 <wushunhao1@huawei.com>
…tale language hint Signed-off-by: w00609601 <wushunhao1@huawei.com>
…mpt-resource-config feat(prompt): unify prompt resource configurability (ADR 0004)
…on base
Introduce ErrorCatalog (42 dotted domain.semantic codes with BUSINESS/INFRA
category and fact-parameter declarations), ErrorMessages renderer over
errors/{lang}/errors.json (en-US fallback), A2ATBusinessException base and
SlotValidationError facts field. A2ATErrorCodes becomes a deprecated
forwarding facade. template_lint gains a catalog-consistency gate.
Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…chema
Rewrite the four error-code prompt groups (content_validation,
slot_extraction, semantic_validation, negotiation_semantic_validation) in
both languages: errors[] items become {slot_name, code, facts} with closed
dotted code sets and three-part definitions, unified terminology
(参数/slot), and the en-US rendered-structure description fixed to match
the actual renderer behavior. Fix the stale missing_input code reference
in the authz slot schema.
Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
DefaultSemanticValidator and DefaultContentValidator parse the new facts schema and render messages via ErrorMessages; the structured slot value extractor emits slot.not_provided / slot.constraint_violated; loader failures map to template.* and infra.* codes; the ValidationPipeline emits final catalog codes directly (the ParamExtractor mapping layer is gone). Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…og codes Migrate generation/validation error codes to the dotted catalog (negotiation.*, llm.*, template.*), re-parent the module business exceptions onto A2ATBusinessException, replace fromData content-data IllegalArguments with coded business exceptions (D7: URI-shape IAEs stay), close the semantic validator code set with domain restriction, and surface LLM-reported slot errors instead of discarding them. Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…aking raw errors Client orchestrator failure codes move to scenario.not_matched / template.* / slot.* with rendered messages and the legacy path now catches and maps previously-uncaught exceptions into result failures; server compliance and semantic validators adopt the facts schema, the slot.* domain restriction and input.text_too_long; both facades' javadocs state the new error contract. Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
Rewrite corpus golden expectations and injected LLM fixtures to the
{slot_name, code, facts} schema and dotted codes, migrate the authz sample
scenario sets and evaluators, and update corpus_review.py code dictionary
to the new codes.
Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
Update API references and developer guides in both languages with the new code table, the errors[] facts schema, rendered-message behavior (language follows A2AT_LANGUAGE) and the old-to-new code mapping. Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
…catalog codes Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
Signed-off-by: codetalks-hw <lihaizhen5@huawei.com>
codetalks-hw
force-pushed
the
feat/error-code-catalog
branch
from
August 29, 2026 07:59
2b5fad4 to
4e1cda1
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR feat/error-code-catalog — Error Code & Message Refactor
Summary
Rebuilds the SDK's entire error surface around a single, closed, bilingual error catalog, fixing the inconsistent codes and garbled messages reported in review ("错误码和错误消息狗屁不通").
Before: four parallel error vocabularies (
A2ATErrorCodesexception codes, result failure codes, free-form LLM-instructed codes, uncoded JDK exceptions), the same code carrying up to 17 different messages (negotiation_llm_infrastructure_error), the same semantic under 2–3 different codes (missing_required/missing_input/ bareIllegalArgumentException), an open LLM code set, mixed message languages (hardcoded English, LLM-improvised Chinese, one prompt forcing English even on zh-CN), and error messages generated as LLM free text — the direct source of awkward outputs like "参数章节 '订阅条件' 下没有提供参数值行,参数未被提供。".After: one
ErrorCatalog(42 dotteddomain.semanticcodes, BUSINESS/INFRA category, declared fact parameters), LLM validation steps report structured facts only —{slot_name, code, facts}— and every user-facing message is rendered by the SDK fromerrors/{lang}/errors.jsontemplates, followingA2AT_LANGUAGE. Same semantic ⇒ same code ⇒ same message, deterministically.Key changes
a2a-t-core: newErrorCatalogenum,ErrorMessagesrenderer (classpatherrors/{zh-CN,en-US}/errors.json, en-US fallback),A2ATBusinessExceptionbase (D6 three-layer model: programming errors stay IAE/NPE, business failures carry codes, infra failures areA2ATError);SlotValidationErrorkeepsmessage(now template-rendered) and gains afactsmap;A2ATErrorCodesis a@Deprecated(forRemoval)forwarding facade.{slot_name, code, facts}output schema (nomessage), unified terminology (参数/slot), and the en-US content_validation structural description corrected to match actual renderer behavior (C1). Themessage 必须为英文contradiction is gone.ParamExtractorruntime vocabulary-mapping layer is deleted; negotiationfromDatacontent-data checks moved from bareIllegalArgumentExceptionto coded business exceptions (URI-shape IAEs intentionally stay); previously-uncaught exceptions on the legacygenerateTaskPromptpath are caught and mapped into result failures (P8); LLM slot errors that were silently discarded are now surfaced (P9); server semantic validator restricts LLM codes to itsslot.*domain with a*.rule_violationfallback + WARN for unknown codes (P7 closed).docs/en+docs/zhAPI references and developer guides updated with the new code table, facts schema and old→new mapping;template_lint.pygains a CI gate: prompt code sets ⊆ catalog, every catalog code has zh-CN and en-US templates, template placeholders ⊆ declared fact parameters.Compatibility
Breaking change, error paths only (see docs-local/error-code-refactor-plan.md §六 in the source workspace): facade signatures, success-path structures and config keys are unchanged; all error codes are new values (old→new mapping table in the docs),
errors[]items gainfactsand theirmessagevalues change from LLM free text to rendered templates. Consumers that serializeerrors[]over the wire should upgrade client and server together.Verification
mvn -B clean verifygreen (all 11 modules, ~1,900 tests, 0 failures) after the finalslot.not_providedrename;python tools/template_lint.py --resource-root ...green including the new catalog gate.Commits
feat(core): error catalog, message templates and business exception basefeat(resources): validation prompt error contracts rewritten to facts schemarefactor(prompt): validators and extractors on catalog codesrefactor(negotiation): content and validation errors on catalog codesrefactor(client,server): facades on catalog codes, no more raw-error leakstest(corpus,sample): expectations migrateddocs(en,zh): new error contract documentedKnown follow-ups (not in this PR)
errors/{lang}/errors.jsonloads from the classpath only; a local-file dual-source variant can follow the existing loader pattern later.start/receive/continueNegotiation, deprecated) intentionally untouched, including their old exception codes.