Skip to content

feat(cli): per-message send_at scheduling on messages send + message-to (#623)#48

Merged
mikemolinet merged 2 commits into
mainfrom
feat/messages-send-at
May 10, 2026
Merged

feat(cli): per-message send_at scheduling on messages send + message-to (#623)#48
mikemolinet merged 2 commits into
mainfrom
feat/messages-send-at

Conversation

@mikemolinet
Copy link
Copy Markdown
Collaborator

Summary

Adds optional --send-at (ISO 8601 string) to cueapi messages send and cueapi message-to — ports the private-monorepo cueapi #623 server-side change that's already shipped on POST /v1/messages (MessageCreate.send_at in app/schemas/message.py).

Server contract pinned

  • NULL send_at (default) → send now
  • Future timestamp → message gates inbox-fetch + push delivery until send_at <= now()
  • Past timestamps → forgiving fallback (treated as send-now)
  • Same semantics as cue-fire send_at (PR #618, already shipped via --send-at on cueapi fire)

Wire format

send_at flows in the body of POST /v1/messages, NOT a header. Mirrors the cue-fire send_at transport. Different from idempotency_key, which is a header. Verify-server-transport-per-endpoint pinned in regression-guard tests.

Changes

  • cueapi/cli.py:
    • messages send: new --send-at flag, body-field wiring
    • message-to: new --send-at flag, body-field wiring (parity with messages send)
  • tests/test_cli.py: 4 new tests
    • messages_send: send_at_omitted_by_default, send_at_passed_in_body
    • message_to: send_at_passed_in_body, send_at_omitted_when_unset

Why this PR matters now

This unblocks 2 downstream ports:

  1. cueapi-action: its messages-send shell branch needs the underlying CLI flag to surface --send-at to GitHub Actions callers.
  2. cueapi-cli message-to: parity with messages send — same surface treatment.

Parallels:

Tests

tests/test_cli.py::test_messages_send_send_at_omitted_by_default PASSED
tests/test_cli.py::test_messages_send_send_at_passed_in_body PASSED
tests/test_cli.py::test_message_to_send_at_passed_in_body PASSED
tests/test_cli.py::test_message_to_send_at_omitted_when_unset PASSED
171 passed total

Test plan

  • Local pytest: 171/171 pass
  • Verified server contract via private monorepo app/schemas/message.py MessageCreate.send_at
  • Verified wire format pinned (body, not header) in 2 regression guards
  • CI green
  • Admin-merge per agents-merge-own-PRs directive

🤖 Generated with Claude Code

…e header (Bug cmp03hy9o)

`cueapi agents webhook-secret regenerate <ref>` was making the
POST /v1/agents/{ref}/webhook-secret/regenerate request without
the `X-Confirm-Destructive: true` header that the server requires.
Result: even after the user typed `y` at the confirmation prompt,
the request was rejected HTTP 400 server-side.

Surfaced 2026-05-10 from Phase 2 messaging smoke testing —
identical bug shape to the one already fixed on
`cueapi key webhook-secret regenerate` (which did pass the header).

Mirror the existing pattern: pass the header on the httpx POST
right after the Y/N confirm clears.

Tests:
- New `test_agents_webhook_secret_regenerate_sends_destructive_header`
  pins the header on the wire — same shape as the existing
  `test_key_webhook_secret_regenerate_sends_destructive_header`.
…to (#623)

Adds optional `--send-at` (ISO 8601 string) to `cueapi messages send`
and `cueapi message-to` — ports the private-monorepo cueapi #623
server-side change that's already shipped on POST /v1/messages
(MessageCreate.send_at in app/schemas/message.py).

Server contract pinned:
- NULL send_at (default) → send now
- Future timestamp → message gates inbox-fetch + push delivery until
  send_at <= now()
- Past timestamps → forgiving fallback (treated as send-now)
- Same semantics as cue-fire send_at (PR #618, already shipped)

Wire format: send_at flows in the BODY of POST /v1/messages, NOT a
header. Mirrors the cue-fire send_at transport. Different from
idempotency_key, which is a header. Verify-server-transport-per-
endpoint pinned in tests so a refactor doesn't accidentally promote
it to a header.

Tests:
- messages_send: 2 new (send_at_omitted_by_default, send_at_passed_in_body)
- message_to: 2 new (send_at_passed_in_body, send_at_omitted_when_unset)
- 171/171 pass total

This unblocks the cueapi-action port (its messages-send shell branch
needs the underlying CLI flag to surface --send-at to GitHub Actions
callers). Parallels cueapi-python (already shipped) and cueapi-mcp
(just shipped via PR #33) ports of the same private-monorepo PR #623.
@govindkavaturi-art govindkavaturi-art enabled auto-merge (squash) May 10, 2026 18:27
@mikemolinet mikemolinet merged commit 1b7b970 into main May 10, 2026
5 checks passed
@mikemolinet mikemolinet deleted the feat/messages-send-at branch May 10, 2026 18:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant