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:
+23
-2
@@ -50,6 +50,7 @@ class FakeRuntime implements ConversationRuntime {
|
||||
confirmResult = true;
|
||||
finishResult = true;
|
||||
stopResult = true;
|
||||
resetResult = false;
|
||||
proposals: Proposal[] = [];
|
||||
commandUsers: Record<string, string | undefined> = {};
|
||||
|
||||
@@ -66,8 +67,8 @@ class FakeRuntime implements ConversationRuntime {
|
||||
async confirm(_platform: string, _chatId: string, userId: string) { this.confirmed++; this.commandUsers.confirm = userId; return this.confirmResult; }
|
||||
async finish(_platform: string, _chatId: string, userId: string) { this.finished++; this.commandUsers.finish = userId; return this.finishResult; }
|
||||
async stop(_platform: string, _chatId: string, userId: string) { this.stopped++; this.commandUsers.stop = userId; return this.stopResult; }
|
||||
async reset(_platform: string, _chatId: string, userId: string) { this.commandUsers.reset = userId; return this.resetResult; }
|
||||
listProposals(_platform: string, _chatId: string, userId: string) { this.listed++; this.commandUsers.list = userId; return this.proposals; }
|
||||
async reset() {}
|
||||
status(_platform?: string, _chatId?: string, userId?: string) {
|
||||
this.commandUsers.status = userId;
|
||||
return {
|
||||
@@ -590,6 +591,7 @@ test("status and help reach the runtime or reply directly", async () => {
|
||||
assert.match(help.reply || "", /\/finish/);
|
||||
assert.match(help.reply || "", /\/stop/);
|
||||
assert.match(help.reply || "", /\/cancel/);
|
||||
assert.match(help.reply || "", /\/reset/);
|
||||
runtime.turns[0].resolve("done");
|
||||
await turn;
|
||||
});
|
||||
@@ -654,7 +656,7 @@ test("the list panel orders pending first, then working, queued, proposed, and r
|
||||
|
||||
const list = await gateway.receive(message("/list"), adapter, { synchronous: true });
|
||||
const reply = list.reply || "";
|
||||
const order = ["待确认(等你处理)", "进行中", "排队中", "未确认(proposed)", "最近结束"]
|
||||
const order = ["待确认", "进行中", "排队中", "未确认(proposed)", "最近结束"]
|
||||
.map((section) => reply.indexOf(section));
|
||||
assert.ok(order.every((index) => index >= 0), reply);
|
||||
assert.deepEqual([...order].sort((a, b) => a - b), order);
|
||||
@@ -665,6 +667,25 @@ test("the list panel orders pending first, then working, queued, proposed, and r
|
||||
assert.match(reply, /p-finished「旧任务」(你的)已完成/);
|
||||
});
|
||||
|
||||
test("/reset resets the current conversation session and reminds about unfinished proposals", async () => {
|
||||
const { runtime, gateway } = createGateway();
|
||||
const adapter = recordingAdapter();
|
||||
|
||||
const noSession = await gateway.receive(message("/reset"), adapter, { synchronous: true });
|
||||
assert.equal(noSession.reply, "当前没有需要重置的会话。");
|
||||
|
||||
runtime.resetResult = true;
|
||||
const reset = await gateway.receive(message("/reset"), adapter, { synchronous: true });
|
||||
assert.match(reset.reply || "", /已重置当前对话/);
|
||||
assert.doesNotMatch(reset.reply || "", /未完成任务/);
|
||||
assert.equal(runtime.commandUsers.reset, "user");
|
||||
|
||||
runtime.proposals = [fakeProposal({ id: "p-1", status: "pending", pending: { summary: "s", receivedAt: 1 } })];
|
||||
const reminded = await gateway.receive(message("/reset"), adapter, { synchronous: true });
|
||||
assert.match(reminded.reply || "", /已重置当前对话/);
|
||||
assert.match(reminded.reply || "", /你还有 1 个未完成任务,proposal 板不受影响/);
|
||||
});
|
||||
|
||||
test("the list panel shows other members' proposals without exposing their identity", async () => {
|
||||
const { runtime, gateway } = createGateway();
|
||||
const adapter = recordingAdapter();
|
||||
|
||||
Reference in New Issue
Block a user