File size: 6,755 Bytes
4879fc7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
from fakes import seed_agent, seed_message


def test_raw_post_fans_out_to_mentions_and_humans(env):
    seed_agent(env.hub, "agent-1")
    seed_agent(env.hub, "agent-2")
    r = env.client.post(
        "/v1/messages",
        json={"agent_id": "agent-1", "body": "hi @agent-2, @human-cmpatino and @nobody"},
    )
    assert r.status_code == 201
    data = r.json()
    assert data["mentions_delivered"] == ["agent-2", "human-cmpatino"]

    central = env.hub.buckets[env.settings.central_bucket]
    filename = data["filename"]
    board = central[f"message_board/{filename}"]
    assert central[f"inbox/agent-2/{filename}"] == board  # byte-identical
    assert central[f"inbox/human-cmpatino/{filename}"] == board
    assert f"inbox/nobody/{filename}" not in central
    # board + both copies landed in ONE batch write
    assert env.hub.batch_writes[-1] == [
        f"message_board/{filename}",
        f"inbox/agent-2/{filename}",
        f"inbox/human-cmpatino/{filename}",
    ]


def test_inbox_read_after_write_and_expand(env):
    seed_agent(env.hub, "agent-1")
    seed_agent(env.hub, "agent-2")
    r = env.client.post(
        "/v1/messages", json={"agent_id": "agent-1", "body": "ping @agent-2"}
    )
    filename = r.json()["filename"]
    data = env.client.get("/v1/inbox/agent-2?expand=true").json()
    assert data["count"] == 1 and data["matched"] == 1
    assert data["items"][0]["filename"] == filename
    assert data["items"][0]["frontmatter"]["agent"] == "agent-1"
    # author filter uses the copied message's author
    assert env.client.get("/v1/inbox/agent-2?agent=agent-1").json()["matched"] == 1
    assert env.client.get("/v1/inbox/agent-2?agent=agent-2").json()["matched"] == 0


def test_refs_authors_get_a_copy(env):
    seed_agent(env.hub, "agent-1")
    seed_agent(env.hub, "agent-2")
    seed_message(env.hub, "20260601-100000-000", "agent-2", "earlier work")
    r = env.client.post(
        "/v1/messages",
        json={
            "agent_id": "agent-1",
            "body": "building on this",
            "refs": "20260601-100000-000_agent-2.md",
        },
    )
    assert r.json()["mentions_delivered"] == ["agent-2"]
    assert env.client.get("/v1/inbox/agent-2").json()["count"] == 1


def test_self_mention_is_not_delivered(env):
    seed_agent(env.hub, "agent-1")
    r = env.client.post(
        "/v1/messages", json={"agent_id": "agent-1", "body": "note to @agent-1"}
    )
    assert r.json()["mentions_delivered"] == []


def test_fanout_cap(make_env):
    env = make_env(MENTION_FANOUT_CAP=2)
    seed_agent(env.hub, "agent-1")
    for i in range(2, 6):
        seed_agent(env.hub, f"agent-{i}")
    r = env.client.post(
        "/v1/messages",
        json={"agent_id": "agent-1", "body": "@agent-2 @agent-3 @agent-4 @agent-5"},
    )
    assert r.json()["mentions_delivered"] == ["agent-2", "agent-3"]


def test_bucket_source_variant_fans_out(env):
    seed_agent(env.hub, "agent-1")
    seed_agent(env.hub, "agent-2")
    env.hub.seed(
        "drafts/plan.md",
        "---\ntype: agent\n---\nlong-form plan, cc @agent-2\n",
        bucket="test-org/test-agent-1",
    )
    r = env.client.post(
        "/v1/messages",
        json={"source": "hf://buckets/test-org/test-agent-1/drafts/plan.md"},
    )
    assert r.status_code == 201
    assert r.json()["via"] == "bucket"
    assert r.json()["mentions_delivered"] == ["agent-2"]


def test_human_inbox_is_readable_without_registration(env):
    assert env.client.get("/v1/inbox/human-cmpatino").json()["count"] == 0


def test_unregistered_agent_inbox_404s(env):
    r = env.client.get("/v1/inbox/ghost")
    assert r.status_code == 404
    assert r.json()["error"]["code"] == "NOT_REGISTERED"


def test_inbox_since_high_water_mark_polling(env):
    seed_agent(env.hub, "agent-1")
    seed_agent(env.hub, "agent-2")
    env.client.post("/v1/messages", json={"agent_id": "agent-1", "body": "old @agent-2"})
    first = env.client.get("/v1/inbox/agent-2?limit=1").json()
    high_water = first["items"][0]
    env.client.post("/v1/messages", json={"agent_id": "agent-1", "body": "new @agent-2"})
    fresh = env.client.get(
        f"/v1/inbox/agent-2?expand=true&after={high_water}"
    ).json()
    assert [m["body"].strip() for m in fresh["items"]] == ["new @agent-2"]
    # `matched` counts filter matches; the cursor only trims the page
    assert fresh["matched"] == 2


# ── server-computed `cursor` (WATCH_DESIGN.md Β§4.4) ───────────────────


def test_cursor_is_the_newest_filename_on_the_page(env):
    """The client persists this verbatim instead of computing a maximum from
    record content β€” which is what let a hostile `filename:` frontmatter key pin
    every eq2 watcher's cursor past all future mail."""
    seed_agent(env.hub, "agent-1")
    seed_agent(env.hub, "agent-2")
    env.client.post("/v1/messages", json={"agent_id": "agent-1", "body": "one @agent-2"})
    env.client.post("/v1/messages", json={"agent_id": "agent-1", "body": "two @agent-2"})

    desc = env.client.get("/v1/inbox/agent-2").json()
    newest = max(desc["items"])
    assert desc["cursor"] == newest

    # Independent of `order`: an ascending page reports the same newest name.
    asc = env.client.get("/v1/inbox/agent-2?order=asc").json()
    assert asc["cursor"] == newest
    # ...and of `expand`.
    exp = env.client.get("/v1/inbox/agent-2?expand=true").json()
    assert exp["cursor"] == newest


def test_cursor_is_null_on_an_empty_page(env):
    """Null, not "" and not the previous value β€” an empty page must not move a
    client's read position."""
    seed_agent(env.hub, "agent-1")
    data = env.client.get("/v1/inbox/agent-1").json()
    assert data["items"] == [] and data["cursor"] is None


def test_cursor_tracks_the_page_not_the_folder(env):
    """With a limit, the cursor is the newest item the caller actually RECEIVED
    β€” advancing past unseen messages would skip them silently."""
    seed_agent(env.hub, "agent-1")
    seed_agent(env.hub, "agent-2")
    for i in range(3):
        env.client.post(
            "/v1/messages", json={"agent_id": "agent-1", "body": f"m{i} @agent-2"}
        )
    page = env.client.get("/v1/inbox/agent-2?order=asc&limit=2").json()
    assert len(page["items"]) == 2
    assert page["cursor"] == page["items"][-1]
    # The third message is still unread and reachable from that cursor.
    rest = env.client.get(f"/v1/inbox/agent-2?order=asc&after={page['cursor']}").json()
    assert len(rest["items"]) == 1


def test_no_watch_block_without_wait(env):
    """A wait=0 caller's response shape is unchanged by this feature."""
    seed_agent(env.hub, "agent-1")
    assert env.client.get("/v1/inbox/agent-1").json()["watch"] is None