feat: share finish stop and cancel across the board
Proposal visibility is already global; this change makes finish, stop, and cancel shared queue-management actions so any user can unblock the single worker and shared queue. Confirm, adjust, follow_up, and start_next remain owner-only. Assistant/bootstrap copy, /help, /list, and runtime checks now align with that split.
This commit is contained in:
@@ -392,18 +392,19 @@ test("proposals are owned per chat+user: a second user in the same chat cannot c
|
||||
assert.equal(await harness.manager.confirm("webhook", "chat-1", "user-b"), false);
|
||||
await harness.manager.prompt(request("confirm", "user-b"));
|
||||
assert.equal(harness.proposals.get(proposal.id)!.status, "proposed");
|
||||
assert.equal(await harness.manager.cancel("webhook", "chat-1", "user-b"), false);
|
||||
await harness.manager.prompt(request("cancel proposal", "user-b"));
|
||||
assert.equal(harness.proposals.get(proposal.id)!.status, "proposed");
|
||||
assert.equal(await harness.manager.finish("webhook", "chat-1", "user-b"), false);
|
||||
assert.equal(await harness.manager.stop("webhook", "chat-1", "user-b"), false);
|
||||
assert.equal(await harness.manager.cancel("webhook", "chat-1", "user-b"), true);
|
||||
assert.equal(harness.proposals.get(proposal.id)!.status, "finished");
|
||||
assert.equal(harness.proposals.get(proposal.id)!.finishKind, "cancelled");
|
||||
|
||||
await harness.manager.prompt(request("create proposal: hang", "user-a"));
|
||||
const running = harness.proposals.list().find((item) => item.status === "proposed")!;
|
||||
|
||||
// The board is globally visible: both users see the same proposal, tagged by scope.
|
||||
assert.equal(harness.manager.listProposals("webhook", "chat-1", "user-b").length, 1);
|
||||
assert.equal(harness.manager.listProposals("webhook", "chat-1", "user-a").length, 1);
|
||||
assert.equal(harness.manager.listProposals("webhook", "chat-1", "user-b").some((item) => item.id === running.id), true);
|
||||
assert.equal(harness.manager.listProposals("webhook", "chat-1", "user-a").some((item) => item.id === running.id), true);
|
||||
|
||||
assert.equal(await harness.manager.confirm("webhook", "chat-1", "user-a"), true);
|
||||
assert.equal(harness.proposals.get(proposal.id)!.status, "working");
|
||||
assert.equal(harness.proposals.get(running.id)!.status, "working");
|
||||
|
||||
await harness.manager.prompt(request("hello owner", "user-a"));
|
||||
const aPrompt = readLog(harness.logFile).find((entry) => entry.method === "session/prompt" && entry.text?.startsWith("[User message]\nhello owner"));
|
||||
@@ -420,11 +421,11 @@ test("proposals are owned per chat+user: a second user in the same chat cannot c
|
||||
assert.match(bPrompt.text!, /scope=other chat=direct/);
|
||||
assert.doesNotMatch(bPrompt.text!, /user-a/);
|
||||
|
||||
assert.equal(await harness.manager.stop("webhook", "chat-1", "user-b"), false);
|
||||
assert.equal(harness.proposals.get(proposal.id)!.status, "working");
|
||||
assert.equal(await harness.manager.stop("webhook", "chat-1", "user-a"), true);
|
||||
assert.equal(harness.proposals.get(proposal.id)!.status, "pending");
|
||||
assert.equal(harness.proposals.get(proposal.id)!.pending?.summary, "被用户中止");
|
||||
assert.equal(await harness.manager.stop("webhook", "chat-1", "user-b"), true);
|
||||
assert.equal(harness.proposals.get(running.id)!.status, "pending");
|
||||
assert.equal(harness.proposals.get(running.id)!.pending?.summary, "被用户中止");
|
||||
assert.equal(await harness.manager.finish("webhook", "chat-1", "user-b"), true);
|
||||
assert.equal(harness.proposals.get(running.id)!.status, "finished");
|
||||
} finally {
|
||||
await closeHarness(harness);
|
||||
}
|
||||
@@ -662,32 +663,44 @@ test("a working proposal blocks start_next for everyone with a sanitized reason"
|
||||
}
|
||||
});
|
||||
|
||||
test("confirm, finish, stop, cancel, and follow_up actions with no matching proposal append an ownership correction", async () => {
|
||||
test("confirm and follow_up stay owner-only while finish, stop, and cancel are shared", async () => {
|
||||
const harness = await createHarness();
|
||||
try {
|
||||
await harness.manager.prompt(request("create proposal: hang", "user-a"));
|
||||
const proposed = harness.proposals.list()[0]!;
|
||||
|
||||
const confirmed = await harness.manager.prompt(request("confirm", "user-b"));
|
||||
assert.match(confirmed.text, /没有可确认的提案/);
|
||||
assert.match(confirmed.text, /自己发起/);
|
||||
|
||||
const cancelled = await harness.manager.prompt(request("cancel proposal", "user-b"));
|
||||
assert.equal(cancelled.text, "cancelling");
|
||||
assert.equal(harness.proposals.get(proposed.id)!.status, "finished");
|
||||
assert.equal(harness.proposals.get(proposed.id)!.finishKind, "cancelled");
|
||||
|
||||
await harness.manager.prompt(request("create proposal: ask", "user-a"));
|
||||
const pending = harness.proposals.list().find((proposal) => proposal.status === "proposed")!;
|
||||
await harness.manager.prompt(request("confirm", "user-a"));
|
||||
await waitFor(() => harness.proposals.get(pending.id)!.status === "pending");
|
||||
|
||||
const finished = await harness.manager.prompt(request("finish", "user-b"));
|
||||
assert.match(finished.text, /没有可结束的任务/);
|
||||
assert.match(finished.text, /自己发起/);
|
||||
assert.equal(finished.text, "finishing");
|
||||
assert.equal(harness.proposals.get(pending.id)!.status, "finished");
|
||||
assert.equal(harness.proposals.get(pending.id)!.finishKind, "done");
|
||||
|
||||
await harness.manager.prompt(request("create proposal: hang", "user-a"));
|
||||
const running = harness.proposals.list().find((proposal) => proposal.status === "proposed")!;
|
||||
await harness.manager.prompt(request("confirm", "user-a"));
|
||||
assert.equal(harness.proposals.get(running.id)!.status, "working");
|
||||
|
||||
const stopped = await harness.manager.prompt(request("stop", "user-b"));
|
||||
assert.match(stopped.text, /没有可停止的任务/);
|
||||
assert.match(stopped.text, /自己发起/);
|
||||
|
||||
const cancelled = await harness.manager.prompt(request("cancel proposal", "user-b"));
|
||||
assert.match(cancelled.text, /没有可取消的提案/);
|
||||
assert.match(cancelled.text, /自己发起/);
|
||||
assert.equal(stopped.text, "stopping");
|
||||
assert.equal(harness.proposals.get(running.id)!.status, "pending");
|
||||
assert.equal(harness.proposals.get(running.id)!.pending?.summary, "被用户中止");
|
||||
|
||||
const followedUp = await harness.manager.prompt(request("follow up: more", "user-b"));
|
||||
assert.match(followedUp.text, /现在没法继续/);
|
||||
assert.match(followedUp.text, /自己发起/);
|
||||
|
||||
assert.equal(harness.proposals.list()[0]!.status, "proposed");
|
||||
} finally {
|
||||
await closeHarness(harness);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user