Feat/support ref implementation#92
Conversation
Signed-off-by: James Hateley <jhateley@godaddy.com>
Signed-off-by: James Hateley <jhateley@godaddy.com>
Signed-off-by: James Hateley <jhateley@godaddy.com>
| if ("self".equals(link.getRel()) && link.getHref() != null) { | ||
| if ("self".equals(link.getRel())) { |
There was a problem hiding this comment.
Why do we remove the null check on link.getHref() here?
There was a problem hiding this comment.
reverted - test cases added.
| // Handle both enum name (HTTP_API) and value (HTTP-API) | ||
| return protocolStr.equals(endpointProtocol.name()) | ||
| || protocolStr.equals(endpointProtocol.getValue()); | ||
| // Normalize hyphens to underscores so "HTTP-API" form matches HTTP_API | ||
| String normalized = protocolStr.replace('-', '_'); | ||
| return normalized.equals(endpointProtocol.name()) | ||
| || normalized.equals(endpointProtocol.getValue()); |
There was a problem hiding this comment.
After normalizing protocolStr to use underscores, the second comparison against getValue() (which returns e.g. "HTTP_API") is redundant with the first comparison against name() — they return the same string for the new top-level Protocol enum. The second clause is effectively dead.
If the intent is to keep both the legacy hyphenated alias and the canonical form working, the original protocolStr should still be compared against getValue() before normalization:
return protocolStr.equals(endpointProtocol.name())
|| protocolStr.equals(endpointProtocol.getValue())
|| protocolStr.replace('-', '_').equals(endpointProtocol.name());Alternatively, we can remove the 2nd OR branch.
There was a problem hiding this comment.
The Protocol enum still contains an entry where the name doesn't match the value:
A2_A("A2A")
so I think we still need this. There is an existing test in AgentConnectionTest:
@Test
void supportsProtocolWithSupportedProtocolShouldReturnTrue() {
// Given
AgentConnection connection = new AgentConnection(agentDetails, ansHttpClient);
// When/Then - using enum name format
assertThat(connection.supportsProtocol("HTTP_API")).isTrue();
assertThat(connection.supportsProtocol("A2A")).isTrue();
}
| String serializeToJsonWithoutField(Object object, String fieldName) { | ||
| try { | ||
| JsonNode tree = objectMapper.readTree(objectMapper.writeValueAsString(object)); | ||
| if (tree instanceof ObjectNode objectNode) { | ||
| objectNode.remove(fieldName); | ||
| } | ||
| return objectMapper.writeValueAsString(tree); | ||
| } catch (IOException e) { | ||
| throw new AnsServerException("Failed to serialize request: " + e.getMessage(), 0, e, null); | ||
| } | ||
| } |
There was a problem hiding this comment.
Minor one - According to Claude, line 185 serializes to string then immediately re-parses. objectMapper.valueToTree(object) avoids the intermediate string allocation:
JsonNode tree = objectMapper.valueToTree(object);
if (tree instanceof ObjectNode objectNode) {
objectNode.remove(fieldName);
}
return objectMapper.writeValueAsString(tree);Signed-off-by: James Hateley <jhateley@godaddy.com>
Related issue
Fixes #91
Summary
Consequences of the v2 spec's model changes:
New files
ApiVersion.java(ans-sdk-core/config) — enumV1(/v1/agents) |V2(/v2/ans/agents). V2 is the default for new clients; both lanes stay live.AgentPaths.java(ans-sdk-registration) — central path builder:agentsCollectionPath(...)registerPath(...)— v2 = collectionPOST, v1 =/registerverbagentPath(version, id, ...segments)AnsConfigurationapiVersionfield + builder setter (defaultsV2, null-checked).environmentrequired → nowenvironmentorbaseUrlrequired.RegistrationClientapiVersion(...)builder method → forwards to config.configurationintoRegistrationService.RegistrationService(version-aware)AnsConfiguration, readsapiVersion.AgentPaths(register / get / verify-acme / verify-dns / revoke).discoveryProfilesfield from the wire body; follow HATEOASselflink for details.pending.getAgentId()(UUID) directly to fetch details; throw if missing.CertificateService(version-aware)apiVersion; identity/server cert paths viaAgentPaths.AnsApiClientserializeToJsonWithoutField(obj, field)— strips a top-level JSON field (e.g.discoveryProfiles) for v1 without mutating the caller's object.ResolutionService/v1/agents/resolution,/v1/agents/{id}) — no v2 equivalent by design.Tests
CertificateServiceTest— add v1-lane routing tests; flip existing stubs/v1/agents/...→/v2/ans/agents/...(v2 now default).RegistrationClientTest— same v2-default path flips (/v1/agents/register→/v2/ans/agents, etc.).Testing
Tests updated, e2e tests ran against local RA (v2) and separate (v1) implementation
AI assistance
None
Checklist
git commit -s) certifying the DCO