Implement inbox read cursors for unread threads

This commit is contained in:
2026-03-19 03:43:10 +08:00
parent 02d98a78dd
commit 1927930570
19 changed files with 240 additions and 38 deletions
+103
View File
@@ -316,6 +316,7 @@ func TestInboxRenewWaitReplyAndCancel(t *testing.T) {
go func() {
stdout, stderr, exitCode := executeInboxCommand(
"--db", dbPath,
"--agent", "worker-c",
"--json",
"wait-reply",
"--thread", threadID,
@@ -359,6 +360,18 @@ func TestInboxRenewWaitReplyAndCancel(t *testing.T) {
t.Fatalf("expected answer wake message, got %q", kind)
}
stdout, _, exitCode := executeInboxCommand(
"--db", dbPath,
"--agent", "worker-c",
"--json",
"fetch",
"--status", "blocked",
"--unread",
)
if exitCode != 10 {
t.Fatalf("expected blocked unread list to be cleared after wait-reply, got exit %d with %s", exitCode, stdout)
}
cancelOut := runInboxCommand(
t,
"--db", dbPath,
@@ -533,6 +546,96 @@ func TestInboxWatchListUnreadAndAppend(t *testing.T) {
}
}
func TestInboxUnreadReadCursor(t *testing.T) {
t.Parallel()
dbPath := filepath.Join(t.TempDir(), "coord.db")
runInboxCommand(t, "--db", dbPath, "--json", "init")
sendOut := runInboxCommand(
t,
"--db", dbPath,
"--json",
"send",
"--from", "leader",
"--to", "worker-e",
"--subject", "Review navbar copy",
"--summary", "Check top nav wording",
)
var sendResp map[string]any
mustDecodeJSON(t, sendOut, &sendResp)
threadID := nestedString(t, sendResp, "data", "thread", "thread_id")
fetchOut := runInboxCommand(
t,
"--db", dbPath,
"--json",
"fetch",
"--agent", "worker-e",
"--status", "pending",
"--unread",
)
var fetchResp map[string]any
mustDecodeJSON(t, fetchOut, &fetchResp)
threads, ok := nestedValue(t, fetchResp, "data", "threads").([]any)
if !ok || len(threads) != 1 {
t.Fatalf("expected one unread pending thread, got %#v", nestedValue(t, fetchResp, "data", "threads"))
}
runInboxCommand(
t,
"--db", dbPath,
"--agent", "worker-e",
"--json",
"show",
"--thread", threadID,
"--mark-read",
)
stdout, _, exitCode := executeInboxCommand(
"--db", dbPath,
"--json",
"fetch",
"--agent", "worker-e",
"--status", "pending",
"--unread",
)
if exitCode != 10 {
t.Fatalf("expected unread fetch to clear after mark-read, got exit %d with %s", exitCode, stdout)
}
runInboxCommand(
t,
"--db", dbPath,
"--json",
"send",
"--from", "leader",
"--to", "worker-e",
"--thread", threadID,
"--summary", "Use sentence case",
"--body", "Keep the nav labels in sentence case.",
)
fetchOut = runInboxCommand(
t,
"--db", dbPath,
"--json",
"fetch",
"--agent", "worker-e",
"--status", "pending",
"--unread",
)
mustDecodeJSON(t, fetchOut, &fetchResp)
threads, ok = nestedValue(t, fetchResp, "data", "threads").([]any)
if !ok || len(threads) != 1 {
t.Fatalf("expected unread thread to reappear after new message, got %#v", nestedValue(t, fetchResp, "data", "threads"))
}
}
func TestInboxJSONErrorsAndExitCodes(t *testing.T) {
t.Parallel()