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
2 changes: 1 addition & 1 deletion amplifier_web/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
"""Amplifier's local web host."""
__version__ = "0.96.3"
__version__ = "0.96.4"
14 changes: 12 additions & 2 deletions amplifier_web/collaboration.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,9 +557,19 @@ def current(self, sid):
WHERE json_extract(receipt,'$.commandAction')='coordination.grant'
AND EXISTS (SELECT 1 FROM json_each(json_extract(receipt,'$.result.participants')) WHERE value=?)
ORDER BY rowid DESC LIMIT 32""", (sid,)).fetchall()]
# Each indexed side contributes at most 32 candidates. An older row
# cannot enter the combined newest 32; UNION deduplicates self-sends.
requests = [json.loads(row[0]) for row in self.service.db.execute("""SELECT receipt FROM commands
WHERE json_extract(receipt,'$.commandAction')='coordination.send'
AND (json_extract(receipt,'$.senderSessionId')=? OR json_extract(receipt,'$.target.sessionId')=?)
WHERE rowid IN (
SELECT rowid FROM (SELECT rowid FROM commands
WHERE json_extract(receipt,'$.commandAction')='coordination.send'
AND json_extract(receipt,'$.senderSessionId')=?
ORDER BY rowid DESC LIMIT 32)
UNION
SELECT rowid FROM (SELECT rowid FROM commands
WHERE json_extract(receipt,'$.commandAction')='coordination.send'
AND json_extract(receipt,'$.target.sessionId')=?
ORDER BY rowid DESC LIMIT 32))
ORDER BY rowid DESC LIMIT 32""", (sid, sid)).fetchall()]
from .request_cancellation import status as cancellation_status
for request in requests:
Expand Down
1 change: 1 addition & 0 deletions amplifier_web/release-notes.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"schemaVersion": 1,
"releases": [
{"version":"0.96.4","title":"Keep busy conversations responsive as coordination history grows","changes":["Recent coordination updates now read only the newest matching requests, reducing repeated work while managers and workers exchange messages. Saved request order, cancellation status and history remain unchanged."],"notices":[]},
{"version":"0.96.3","title":"Keep busy workspaces responsive","changes":["Browser updates share one notice-counting pass, reducing repeated database work while chats and tools are active. Unread counts, approvals, errors and saved conversations retain their existing behavior."],"notices":[]},
{"version":"0.96.2","title":"Keep context-limit recovery connected to the original request","changes":["Preserve a model provider's context-limit feedback when the host adds the selected model and current observations to a request, so the existing recovery path can use the feedback instead of losing it between request wrappers.","Keep recovery tied to the exact failed request and its options. Changed requests, feedback already consumed, and errors after streamed output do not start another recovery attempt; Stop and completed-tool receipts remain intact.","Add regression coverage for cold Fable 5.2 counting, recovery during a long tool turn, resumed signed history, a second context-limit refusal and Stop. The upstream cold-model fix is selected in development checks; installed provider components still update through the normal component-update path.","Package workspace registration metadata from its published 0.1.0 component, including its source and license records. The runtime code and workspace behavior are unchanged."],"notices":[]},
{"version":"0.96.1","title":"Published operations component, unchanged runtime behavior","changes":["Unified now selects the original published operations 0.1.0 artifact and verifies its runtime bytes offline. Independent component authoring moves to components/operations, while the selected top-level runtime keeps the existing editable and isolated-worker imports. Unified remains the only installed distribution owner; operation behavior, durable receipts, cursors, authority and Stop controls are unchanged. The app package adds the selected artifact's provenance and license records; it does not republish the component.","Component release tooling now supports the independent workspace-metadata publication path, without changing Unified's selected runtime or coinstalling a standalone package. MCP guidance documents the released error-fidelity adapter in its explicit opt-in profile."],"notices":[]},
Expand Down
9 changes: 9 additions & 0 deletions docs/validation/performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,15 @@ checks retain global positions, negative indices, private-state filtering and
stale-revision refusal. Their SQL budgets measure query work, not constant-time
global ordering or a guaranteed live-host latency.

`tests/test_coordination_current_cost.py` grows unrelated, incoming and outgoing
command history while holding the current 32-request page fixed. Select bounded
candidate IDs through the existing sender/target indexes before fetching bodies;
the final page keeps insertion order and deduplicates requests involving both
sides. Reads stay on the caller's transaction and observe uncommitted receipt
changes and rollback. Cancellation remains a projection of the saved receipt,
not a rewritten outcome. The measured query bound does not cover initial index
creation, grants, pending proposals or other coordination operations.

The additive Extended browser registration belongs to the nightly/manual lane. The separate
`Client performance smoke` workflow selects affected PR paths and supports manual
runs; it is not a required status or a publication dependency. Run it locally in
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "amplifier-unified"
version = "0.96.3"
version = "0.96.4"
description = "A local voice-first Amplifier workspace with a shared user and agent interface"
readme = "README.md"
requires-python = ">=3.13"
Expand Down
102 changes: 102 additions & 0 deletions tests/test_coordination_current_cost.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""Bound current receipt lookup before decoding retained request bodies."""
import json
import time

import pytest

from test_coordination import app # noqa: F401 -- actual host/index fixture


def request(identity, sender, target, **changes):
return {"requestId": identity, "commandAction": "coordination.send",
"senderSessionId": sender, "target": {"sessionId": target},
"delivery": "accepted", "acceptedAt": 0, **changes}


def insert(db, rows):
db.executemany("INSERT INTO commands(id,fingerprint,receipt) VALUES(?,?,?)",
((row["requestId"], row["requestId"], json.dumps(row)) for row in rows))


@pytest.mark.parametrize("retained_kind", ["unrelated", "outgoing", "incoming"])
async def test_current_receipt_work_is_bounded_by_the_page(app, retained_kind):
sid, peer = (row["id"] for row in app.state["sessions"])
sender = sid if retained_kind == "outgoing" else "elsewhere"
target = sid if retained_kind == "incoming" else "another-peer"
measurements = []
for count in (50, 5000):
app.db.execute("DELETE FROM commands")
insert(app.db, (request(f"old-{i}", sender, target, text="retained" * 256)
for i in range(count)))
recent = [request(f"recent-{i}", sid if i % 2 else peer,
peer if i % 2 else sid) for i in range(48)]
insert(app.db, recent)
app.db.commit()
steps = 0

def progress():
nonlocal steps
steps += 100
return 0

app.db.set_progress_handler(progress, 100)
start = time.thread_time_ns()
try:
actual = app.collaboration.current(sid)["requests"]
finally:
app.db.set_progress_handler(None, 0)
measurements.append({"retained": count, "vm": steps,
"cpuMs": (time.thread_time_ns() - start) / 1e6})
assert actual == list(reversed(recent))[:32]
print(json.dumps({"currentReceipts": retained_kind, "measurements": measurements}))
# A fixed current page must not parse/filter every retained peer request,
# including older requests involving this same conversation. Count actual
# SQLite work, not just the 32 returned/decoded rows or elapsed time.
assert measurements[1]["vm"] < 5000
assert measurements[1]["vm"] <= measurements[0]["vm"] + 500


async def test_current_receipts_keep_order_deduplication_and_saved_bodies(app):
sid, peer = (row["id"] for row in app.state["sessions"])
rows = [request(f"request-{i}", sid if i % 2 else peer,
sid if i % 3 else peer, acceptedAt=1000-i,
text=f"Saved body {i}: \u2603", detail={"nested": [i]})
for i in range(90)]
# Sender-only and target-only records are still selected. A same-owner
# request appears once, including at a page boundary; dates do not reorder.
rows[-1].pop("target")
rows[-2].pop("senderSessionId")
rows[-3].update(senderSessionId=sid, target={"sessionId": sid},
cancellation={"status": "requested", "revision": 2})
rows[-4]["commandAction"] = "unrelated.action"
insert(app.db, rows)
expected = [row for row in reversed(rows)
if row["commandAction"] == "coordination.send"
and (row.get("senderSessionId") == sid
or row.get("target", {}).get("sessionId") == sid)][:32]
actual = app.collaboration.current(sid)["requests"]
assert actual == expected
assert len({row["requestId"] for row in actual}) == 32
actual[0]["detail"]["nested"].append("borrowed edit")
assert app.collaboration.current(sid)["requests"] == expected


async def test_current_receipts_observe_updates_and_transaction_rollback(app):
sid, peer = (row["id"] for row in app.state["sessions"])
original = request("original", peer, sid, cancellation={"status": "requested"})
insert(app.db, [original])
app.db.commit()
app.db.execute("SAVEPOINT receipt_change")
changed = {**original, "delivery": "held", "text": "not admitted"}
app.collaboration.save("original", changed)
insert(app.db, [request("new", sid, peer)])
value = app.collaboration.current(sid)["requests"]
assert [row["requestId"] for row in value] == ["new", "original"]
assert value[1]["cancellation"]["status"] == "withdrawn"
# The read projection never rewrites the historical cancellation receipt.
assert app.collaboration.receipt("original")["cancellation"] == {"status": "requested"}
app.db.execute("ROLLBACK TO receipt_change")
app.db.execute("RELEASE receipt_change")
assert app.collaboration.current(sid)["requests"] == [original]
app.db.execute("DELETE FROM commands WHERE id='original'")
assert app.collaboration.current(sid)["requests"] == []
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading