Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion cueapi/resources/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ def subscriptions_create(
event_type: str,
delivery_target: str,
webhook_url: Optional[str] = None,
inline_body: Optional[bool] = None,
) -> Dict[str, Any]:
"""Create a subscription for an agent (PR-1b event-emit primitive).

Expand All @@ -266,11 +267,22 @@ def subscriptions_create(
``"webhook"`` (server POSTs to ``webhook_url`` with HMAC).
webhook_url: Required when ``delivery_target="webhook"``;
HTTPS only. Ignored for pull subscriptions.
inline_body: Opt into body embedding on emitted events
(server Item 1, hosted PR #791). When ``True``, the source
message body is embedded in the event payload as
``payload.body`` — eliminates the extra
``GET /v1/messages/{id}`` round-trip on the consumer side.
Bodies > 32KB are NOT embedded; instead the payload carries
``payload.body_omitted = "size_too_large"`` and
``payload.body_size_bytes = N`` so consumers can fall back
to the fetch. Default ``None`` means "don't send the field"
— server default is ``False``.

Returns:
Subscription dict. For webhook subscriptions, the response
includes ``webhook_secret`` ONE-TIME — save it now; the
server never re-exposes it.
server never re-exposes it. Both pull and webhook responses
surface ``inline_body`` so list-callers can observe own state.

Errors:
400 ``unknown_event_type`` / ``invalid_delivery_target`` /
Expand All @@ -282,6 +294,8 @@ def subscriptions_create(
}
if webhook_url is not None:
body["webhook_url"] = webhook_url
if inline_body is not None:
body["inline_body"] = inline_body
return self._client._post(f"/v1/agents/{ref}/subscriptions", json=body)

def subscriptions_list(self, ref: str) -> Dict[str, Any]:
Expand Down
61 changes: 61 additions & 0 deletions tests/test_agents_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,67 @@ def test_webhook_url_omitted_when_none(self):
body = mock_client._post.call_args.kwargs["json"]
assert "webhook_url" not in body

def test_inline_body_omitted_when_none(self):
# Server-side default is False; sending an unset kwarg should
# NOT put the field on the wire (avoid payload noise for
# callers who don't care about body embedding).
mock_client = MagicMock()
mock_client._post.return_value = {"id": "sub_uuid"}
r = AgentsResource(mock_client)

r.subscriptions_create(
"agt_x",
event_type="message.received",
delivery_target="pull",
)

body = mock_client._post.call_args.kwargs["json"]
assert "inline_body" not in body

def test_inline_body_true_passes_through(self):
# Opt-in: inline_body=True embeds message.body on emitted events
# (server Item 1, hosted PR #791).
mock_client = MagicMock()
mock_client._post.return_value = {
"id": "sub_uuid",
"delivery_target": "pull",
"inline_body": True,
}
r = AgentsResource(mock_client)

r.subscriptions_create(
"agt_x",
event_type="message.received",
delivery_target="pull",
inline_body=True,
)

body = mock_client._post.call_args.kwargs["json"]
assert body["inline_body"] is True

def test_inline_body_false_explicit_passes_through(self):
# Explicit False (distinct from None / unset) — caller may want
# to force the no-embed contract on a per-subscription basis.
# We pass it through verbatim; server treats False the same as
# the schema default but explicit is non-noisy.
mock_client = MagicMock()
mock_client._post.return_value = {
"id": "sub_uuid",
"delivery_target": "pull",
"inline_body": False,
}
r = AgentsResource(mock_client)

r.subscriptions_create(
"agt_x",
event_type="message.received",
delivery_target="pull",
inline_body=False,
)

body = mock_client._post.call_args.kwargs["json"]
assert body["inline_body"] is False


class TestSubscriptionsList:
def test_get_path(self):
Expand Down
Loading