mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-18 06:13:19 +08:00
fix: preserve error reactions for failed interactions
This commit is contained in:
parent
da01e3acee
commit
1445b93891
3 changed files with 31 additions and 5 deletions
File diff suppressed because one or more lines are too long
|
|
@ -866,6 +866,7 @@ export class TextHarnessBridge {
|
||||||
try {
|
try {
|
||||||
await this.#presentInteraction(pending);
|
await this.#presentInteraction(pending);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
message.statusReaction?.error();
|
||||||
this.#status.lastError = t('{label}交互问题发送失败。', { label: this.#descriptor.label });
|
this.#status.lastError = t('{label}交互问题发送失败。', { label: this.#descriptor.label });
|
||||||
this.#logger.error?.(
|
this.#logger.error?.(
|
||||||
`[dsh-im:${this.#descriptor.key}] failed to retry an interaction question:`,
|
`[dsh-im:${this.#descriptor.key}] failed to retry an interaction question:`,
|
||||||
|
|
@ -904,6 +905,7 @@ export class TextHarnessBridge {
|
||||||
try {
|
try {
|
||||||
await this.#presentInteraction(pending);
|
await this.#presentInteraction(pending);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
message.statusReaction?.error();
|
||||||
this.#status.lastError = t('{label}交互问题发送失败。', { label: this.#descriptor.label });
|
this.#status.lastError = t('{label}交互问题发送失败。', { label: this.#descriptor.label });
|
||||||
this.#logger.error?.(
|
this.#logger.error?.(
|
||||||
`[dsh-im:${this.#descriptor.key}] failed to send the next interaction question:`,
|
`[dsh-im:${this.#descriptor.key}] failed to send the next interaction question:`,
|
||||||
|
|
@ -946,7 +948,11 @@ export class TextHarnessBridge {
|
||||||
message.statusReaction?.clear();
|
message.statusReaction?.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.#pendingInteractions.get(key) !== pending) return;
|
if (this.#pendingInteractions.get(key) !== pending) {
|
||||||
|
message.statusReaction?.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
message.statusReaction?.error();
|
||||||
pending.submitting = false;
|
pending.submitting = false;
|
||||||
pending.answers.pop();
|
pending.answers.pop();
|
||||||
pending.index -= 1;
|
pending.index -= 1;
|
||||||
|
|
|
||||||
|
|
@ -141,9 +141,10 @@ function createBridge({
|
||||||
bot,
|
bot,
|
||||||
signal,
|
signal,
|
||||||
logger,
|
logger,
|
||||||
|
reactions,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
return new TextHarnessBridge({
|
return new TextHarnessBridge({
|
||||||
descriptor: { key: 'test', label: 'Test' },
|
descriptor: { key: 'test', label: 'Test', reactions },
|
||||||
bot,
|
bot,
|
||||||
harness,
|
harness,
|
||||||
state,
|
state,
|
||||||
|
|
@ -2264,11 +2265,22 @@ test('deduplicates replays and safely closes recovered questions and approvals',
|
||||||
test('keeps a failed interaction response pending so the actor can retry', async () => {
|
test('keeps a failed interaction response pending so the actor can retry', async () => {
|
||||||
const fixture = stateFixture();
|
const fixture = stateFixture();
|
||||||
const sent = [];
|
const sent = [];
|
||||||
|
const reactions = [];
|
||||||
const completed = deferred();
|
const completed = deferred();
|
||||||
const submittedAnswers = [];
|
const submittedAnswers = [];
|
||||||
const bridge = createBridge({
|
const bridge = createBridge({
|
||||||
state: fixture.state,
|
state: fixture.state,
|
||||||
bot: { sendText: async (target, text) => sent.push({ target, text }) },
|
reactions: { processing: 'eyes', success: 'done', error: 'error' },
|
||||||
|
bot: {
|
||||||
|
addReaction: async (target, emoji) => {
|
||||||
|
reactions.push(['add', target.id, emoji]);
|
||||||
|
return emoji;
|
||||||
|
},
|
||||||
|
removeReaction: async (target, emoji) => {
|
||||||
|
reactions.push(['remove', target.id, emoji]);
|
||||||
|
},
|
||||||
|
sendText: async (target, text) => sent.push({ target, text }),
|
||||||
|
},
|
||||||
harness: {
|
harness: {
|
||||||
createSession: async () => 'session-one',
|
createSession: async () => 'session-one',
|
||||||
ask: async (sessionId, _text, options) => {
|
ask: async (sessionId, _text, options) => {
|
||||||
|
|
@ -2290,13 +2302,21 @@ test('keeps a failed interaction response pending so the actor can retry', async
|
||||||
|
|
||||||
const processing = bridge.accept(message('retry-start', '启动可重试交互'));
|
const processing = bridge.accept(message('retry-start', '启动可重试交互'));
|
||||||
await eventually(() => sent.some(({ text }) => text.includes('请回答')));
|
await eventually(() => sent.some(({ text }) => text.includes('请回答')));
|
||||||
await bridge.accept(message('retry-first', '第一次答案'));
|
await bridge.accept(message('retry-first', '第一次答案', {
|
||||||
|
reactionTarget: { id: 'source-retry-first' },
|
||||||
|
}));
|
||||||
|
await eventually(() => reactions.length === 3);
|
||||||
assert.equal(sent.some(({ text }) => text.includes('回答提交失败')), true);
|
assert.equal(sent.some(({ text }) => text.includes('回答提交失败')), true);
|
||||||
await bridge.accept(message('retry-second', '重试后的答案'));
|
await bridge.accept(message('retry-second', '重试后的答案'));
|
||||||
await processing;
|
await processing;
|
||||||
|
|
||||||
assert.deepEqual(submittedAnswers, ['第一次答案', '重试后的答案']);
|
assert.deepEqual(submittedAnswers, ['第一次答案', '重试后的答案']);
|
||||||
assert.equal(sent.at(-1).text, '重试成功');
|
assert.equal(sent.at(-1).text, '重试成功');
|
||||||
|
assert.deepEqual(reactions, [
|
||||||
|
['add', 'source-retry-first', 'eyes'],
|
||||||
|
['remove', 'source-retry-first', 'eyes'],
|
||||||
|
['add', 'source-retry-first', 'error'],
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('notifies the actor when an in-flight response resolves elsewhere before rejection', async () => {
|
test('notifies the actor when an in-flight response resolves elsewhere before rejection', async () => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue