Skip to content

Commit 393eb59

Browse files
authored
Merge pull request #153 from Virtual-Protocol/feat/yang-use-sla-minutes-from-be
feat: use sla minutes from be
2 parents 93bf6df + eee616f commit 393eb59

File tree

8 files changed

+15
-39
lines changed

8 files changed

+15
-39
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ chosen_agent = relevant_agents[0]
180180
chosen_agent_offering = chosen_agent.offerings[0]
181181
job_id = chosen_agent_offering.initiate_job(
182182
service_requirement,
183-
expired_at,
184183
evaluator_address
185184
)
186185

examples/acp_base/external_evaluation/buyer.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import logging
22
import threading
3-
from datetime import datetime, timedelta
43
from typing import Optional
54

65
from dotenv import load_dotenv
@@ -85,8 +84,7 @@ def on_new_task(job: ACPJob, memo_to_sign: Optional[ACPMemo] = None):
8584
"<your-schema-key-1>": "<your-schema-value-1>",
8685
"<your-schema-key-2>": "<your-schema-value-2>",
8786
},
88-
evaluator_address=env.EVALUATOR_AGENT_WALLET_ADDRESS, # evaluator address
89-
expired_at=datetime.now() + timedelta(minutes=3.1) # job expiry duration, minimum 3 minutes
87+
evaluator_address=env.EVALUATOR_AGENT_WALLET_ADDRESS, # evaluator address
9088
)
9189

9290
logger.info(f"Job {job_id} initiated")

examples/acp_base/polling_mode/buyer.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import logging
22
import time
3-
from datetime import datetime, timedelta
43

54
from dotenv import load_dotenv
65

@@ -66,7 +65,6 @@ def buyer():
6665
"<your-schema-key-2>": "<your-schema-value-2>",
6766
},
6867
evaluator_address=env.EVALUATOR_AGENT_WALLET_ADDRESS, # evaluator address
69-
expired_at=datetime.now() + timedelta(minutes=3.1), # job expiry duration, minimum 3 minutes
7068
)
7169

7270
logger.info(f"Job {job_id} initiated")

examples/acp_base/skip_evaluation/buyer.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import logging
22
import threading
3-
from datetime import datetime, timedelta
43
from typing import Optional
54

65
from dotenv import load_dotenv
@@ -87,7 +86,6 @@ def on_new_task(job: ACPJob, memo_to_sign: Optional[ACPMemo] = None):
8786
"<your-schema-key-1>": "<your-schema-value-1>",
8887
"<your-schema-key-2>": "<your-schema-value-2>",
8988
},
90-
expired_at=datetime.now() + timedelta(minutes=5), # job expiry duration, minimum 3 minutes
9189
)
9290
logger.info(f"Job {job_id} initiated")
9391
logger.info("Listening for next steps...")

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "virtuals-acp"
3-
version = "0.3.19"
3+
version = "0.3.20"
44
description = "Agent Commerce Protocol Python SDK by Virtuals"
55
authors = ["Steven Lee Soon Fatt <steven@virtuals.io>"]
66
readme = "README.md"

tests/unit/test_job_offering.py

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def basic_offering(self, mock_acp_client, mock_contract_client):
5656
name="Test Service",
5757
price=10.0,
5858
price_type=PriceType.FIXED,
59+
sla_minutes=60,
5960
requirement=None,
6061
deliverable=None
6162
)
@@ -71,6 +72,7 @@ def offering_with_schema(self, mock_acp_client, mock_contract_client):
7172
name="Test Service",
7273
price=10.0,
7374
price_type=PriceType.FIXED,
75+
sla_minutes=60,
7476
requirement={
7577
"type": "object",
7678
"properties": {
@@ -96,6 +98,7 @@ def test_should_initialize_with_required_parameters(
9698
name="Test Service",
9799
price=10.0,
98100
price_type=PriceType.FIXED,
101+
sla_minutes=60,
99102
requirement=None,
100103
deliverable=None
101104
)
@@ -123,6 +126,7 @@ def test_should_initialize_with_optional_parameters(
123126
name="Test Service",
124127
price=10.0,
125128
price_type=PriceType.PERCENTAGE,
129+
sla_minutes=60,
126130
requirement=requirement,
127131
deliverable=deliverable,
128132
)
@@ -145,6 +149,7 @@ def test_should_parse_valid_json_string(
145149
name="Test Service",
146150
price=10.0,
147151
price_type=PriceType.FIXED,
152+
sla_minutes=60,
148153
requirement='{"type": "string"}',
149154
deliverable=None
150155
)
@@ -165,6 +170,7 @@ def test_should_keep_dict_requirement_as_is(
165170
name="Test Service",
166171
price=10.0,
167172
price_type=PriceType.FIXED,
173+
sla_minutes=60,
168174
requirement=requirement,
169175
deliverable=None
170176
)
@@ -195,10 +201,10 @@ class TestInitiateJob:
195201
class TestExpiryHandling:
196202
"""Test expiry date handling"""
197203

198-
def test_should_use_default_expiry_when_none(
204+
def test_should_use_sla_minutes_for_expiry(
199205
self, basic_offering, mock_contract_client
200206
):
201-
"""Should use default 1 day expiry when not provided"""
207+
"""Should use offering sla_minutes for job expiration"""
202208
mock_contract_client.get_job_id.return_value = 123
203209
mock_contract_client.handle_operation.return_value = {}
204210
basic_offering.acp_client.get_by_client_and_provider.return_value = None
@@ -213,35 +219,12 @@ def test_should_use_default_expiry_when_none(
213219
service_requirement={"task": "test"}
214220
)
215221

216-
# Check that create_job was called
217222
create_call = mock_contract_client.create_job.call_args
218223
expired_at = create_call[0][2] # Third positional arg
219224

220-
# Should be 1 day after now
221-
expected = mock_now + timedelta(days=1)
225+
expected = mock_now + timedelta(minutes=basic_offering.sla_minutes)
222226
assert expired_at == expected
223227

224-
def test_should_use_custom_expiry_when_provided(
225-
self, basic_offering, mock_contract_client
226-
):
227-
"""Should use custom expiry when provided"""
228-
mock_contract_client.get_job_id.return_value = 123
229-
mock_contract_client.handle_operation.return_value = {}
230-
basic_offering.acp_client.get_by_client_and_provider.return_value = None
231-
232-
custom_expiry = datetime(
233-
2024, 12, 31, 23, 59, 59, tzinfo=timezone.utc)
234-
235-
basic_offering.initiate_job(
236-
service_requirement={"task": "test"},
237-
expired_at=custom_expiry
238-
)
239-
240-
create_call = mock_contract_client.create_job.call_args
241-
expired_at = create_call[0][2]
242-
243-
assert expired_at == custom_expiry
244-
245228
class TestServiceRequirementValidation:
246229
"""Test service requirement validation"""
247230

virtuals_acp/client.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ def _hydrate_agent(self, agent_data: Dict[str, Any]) -> IACPAgent:
315315
price=price,
316316
price_type=price_type,
317317
required_funds=offering["requiredFunds"],
318+
sla_minutes=offering["slaMinutes"],
318319
requirement=offering.get("requirement", None),
319320
deliverable=offering.get("deliverable", None),
320321
)

virtuals_acp/job_offering.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class ACPJobOffering(BaseModel):
3030
price: float
3131
price_type: PriceType
3232
required_funds: bool
33+
sla_minutes: int
3334
requirement: Optional[Union[Dict[str, Any], str]] = None
3435
deliverable: Optional[Union[Dict[str, Any], str]] = None
3536

@@ -54,10 +55,8 @@ def initiate_job(
5455
self,
5556
service_requirement: Union[Dict[str, Any], str],
5657
evaluator_address: Optional[str] = None,
57-
expired_at: Optional[datetime] = None,
5858
) -> int:
59-
if expired_at is None:
60-
expired_at = datetime.now(timezone.utc) + timedelta(days=1)
59+
expired_at = datetime.now(timezone.utc) + timedelta(minutes=self.sla_minutes)
6160

6261
# Validate against requirement schema if present
6362
if self.requirement:
@@ -139,7 +138,7 @@ def initiate_job(
139138
evaluator_address or self.contract_client.agent_wallet_address,
140139
fare_amount.amount,
141140
fare_amount.fare.contract_address,
142-
expired_at or datetime.utcnow(),
141+
expired_at,
143142
is_x402_job=is_x402_job,
144143
)
145144

0 commit comments

Comments
 (0)