Restore QuoteJudge upload tool compatibility
This commit is contained in:
2
a2a.yaml
2
a2a.yaml
@@ -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
|
||||||
|
|||||||
52
agent.py
52
agent.py
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user