Restore QuoteJudge upload tool compatibility

This commit is contained in:
2026-07-18 02:04:26 -03:00
parent a5da139e60
commit 95ffb50a3a
3 changed files with 61 additions and 5 deletions

View File

@@ -1,5 +1,5 @@
name: quote-judge-studio-v1 name: quote-judge-studio-v1
version: 0.1.0 version: 0.1.2
entrypoint: agent:QuoteJudgeStudioV1 entrypoint: agent:QuoteJudgeStudioV1
expose: expose:
public: false public: false

View File

@@ -8,7 +8,6 @@ Deterministic, no-LLM quote comparison product:
""" """
from __future__ import annotations from __future__ import annotations
import asyncio
import base64 import base64
import csv import csv
import hashlib import hashlib
@@ -88,7 +87,7 @@ class QuoteJudgeStudioV1(A2AAgent[QuoteJudgeStudioV1Config, PlatformUserAuth]):
"and warranty scoring, persists recommendations, supports upload/paste " "and warranty scoring, persists recommendations, supports upload/paste "
"workflows, and exposes typed A2A/MCP tools." "workflows, and exposes typed A2A/MCP tools."
) )
version = "0.1.1" version = "0.1.2"
config_model = QuoteJudgeStudioV1Config config_model = QuoteJudgeStudioV1Config
auth_model = PlatformUserAuth auth_model = PlatformUserAuth
@@ -208,6 +207,26 @@ class QuoteJudgeStudioV1(A2AAgent[QuoteJudgeStudioV1Config, PlatformUserAuth]):
return {**parsed, "comparison_id": comparison_id} return {**parsed, "comparison_id": comparison_id}
return await self.compare_quotes(ctx, comparison_id=comparison_id, quotes=parsed["quotes"], weights=weights) return await self.compare_quotes(ctx, comparison_id=comparison_id, quotes=parsed["quotes"], weights=weights)
@a2a.tool(
description="Compatibility alias for the original QuoteJudge browser upload tool.",
timeout_seconds=60,
idempotent=True,
cost_class="deterministic",
)
async def compare_uploaded_quotes_browser(
self,
ctx: RunContext[PlatformUserAuth],
comparison_id: Annotated[str, Field(min_length=1, max_length=120)],
documents: Annotated[list[BrowserDocument], Field(min_length=1, max_length=MAX_BROWSER_DOCUMENTS)],
weights: QuoteWeights,
) -> dict[str, Any]:
return await self.compare_quotes_from_browser_upload(
ctx,
comparison_id=comparison_id,
documents=documents,
weights=weights,
)
@a2a.tool( @a2a.tool(
description=( description=(
"External API upload path: accept a typed FileUpload containing " "External API upload path: accept a typed FileUpload containing "
@@ -257,6 +276,35 @@ class QuoteJudgeStudioV1(A2AAgent[QuoteJudgeStudioV1Config, PlatformUserAuth]):
return {**parsed, "comparison_id": comparison_id} return {**parsed, "comparison_id": comparison_id}
return await self.compare_quotes(ctx, comparison_id=comparison_id, quotes=parsed["quotes"], weights=weights) return await self.compare_quotes(ctx, comparison_id=comparison_id, quotes=parsed["quotes"], weights=weights)
@a2a.tool(
description="Compatibility alias for the original QuoteJudge external upload tool.",
timeout_seconds=60,
idempotent=True,
cost_class="deterministic",
grant_mode="read_only",
grant_allow_patterns=("**",),
)
async def compare_uploaded_quote_file(
self,
ctx: RunContext[PlatformUserAuth],
comparison_id: Annotated[str, Field(min_length=1, max_length=120)],
document: Annotated[
UploadedFile,
FileUpload(
accept=ACCEPTED_UPLOAD_TYPES,
max_bytes=MAX_BROWSER_DOCUMENT_BYTES,
description="JSON list/object, CSV, or text containing vendor quotes.",
),
],
weights: QuoteWeights,
) -> dict[str, Any]:
return await self.compare_quotes_from_upload(
ctx,
comparison_id=comparison_id,
quote_file=document,
weights=weights,
)
def _tenant_key(ctx: RunContext[PlatformUserAuth]) -> str: def _tenant_key(ctx: RunContext[PlatformUserAuth]) -> str:
auth = ctx.auth auth = ctx.auth

View File

@@ -1,7 +1,6 @@
from __future__ import annotations from __future__ import annotations
import asyncio import asyncio
import os
from pathlib import Path from pathlib import Path
from unittest.mock import patch from unittest.mock import patch
@@ -42,7 +41,16 @@ def test_full_stack_product_contract():
card = load_local_project(ROOT).agent_cls().card() card = load_local_project(ROOT).agent_cls().card()
skill_names = {skill.name for skill in card.skills} skill_names = {skill.name for skill in card.skills}
assert {"compare_quotes", "get_comparison", "compare_quotes_from_browser_upload", "compare_quotes_from_upload"}.issubset(skill_names) assert {
"compare_quotes",
"get_comparison",
"compare_quotes_from_browser_upload",
"compare_quotes_from_upload",
"compare_uploaded_quotes_browser",
"compare_uploaded_quote_file",
}.issubset(skill_names)
assert card.version == "0.1.2"
assert "version: 0.1.2" in (ROOT / "a2a.yaml").read_text(encoding="utf-8")
databases = card.runtime.platform_resources.databases databases = card.runtime.platform_resources.databases
assert databases, "live Agent Card must declare its managed database" assert databases, "live Agent Card must declare its managed database"
assert databases[0].scope == "user" assert databases[0].scope == "user"