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
5 changes: 4 additions & 1 deletion bridge-browser/src/content/result_delivery_controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ export class ResultDeliveryController {
}

this.options.toolActivityTracker.updateDelivery(resultBatch.ids, "delivered");
UI.triggerAutoSend({ autoSend: this.options.getAutoSend() }, selectors);
UI.triggerAutoSend({
autoSend: this.options.getAutoSend(),
hasFileUpload: delivery.uploaded,
}, selectors);
})
.catch((error: unknown) => {
batchFinalized = true;
Expand Down
20 changes: 9 additions & 11 deletions bridge-browser/src/modules/auto_send.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,18 @@ import {
} from "./page_selectors";
import { isElementVisible } from "./dom_helpers";
import { showUserAttentionNotification } from "./user_attention";
import { getAutoSendAction, getAutoSendAttemptLimit } from "./auto_send_policy";

let autoSendTimer: NodeJS.Timeout | null = null;
type AutoSendAction = "ctrl-enter" | "enter" | "button";

const AUTO_SEND_INITIAL_DELAY_MS = 350;
const AUTO_SEND_SETTLE_MS = 1200;
const AUTO_SEND_RETRY_MS = 1600;
const AUTO_SEND_ACTIONS: AutoSendAction[] = [
"enter",
"ctrl-enter",
"button",
"enter",
"ctrl-enter",
];

export interface AutoSendConfig {
autoSend: boolean;
hasFileUpload: boolean;
}

/**
* 终止当前正在进行的自动发送轮询机制
Expand Down Expand Up @@ -51,7 +49,7 @@ export function cancelAutoSend() {
* - 4. 如果所有轮次还是失败,系统会弹出通知警告用户。
*/
export function triggerAutoSend(
config: { autoSend: boolean },
config: AutoSendConfig,
domSelectors: SiteSelectors
) {
if (!config.autoSend) {return;}
Expand All @@ -61,7 +59,7 @@ export function triggerAutoSend(
}

let retryCount = 0;
const maxRetries = AUTO_SEND_ACTIONS.length;
const maxRetries = getAutoSendAttemptLimit(config.hasFileUpload);

const getInputEl = () => getInputAreaElement(domSelectors);
const getInputValue = (inputEl: HTMLElement): string => {
Expand Down Expand Up @@ -107,7 +105,7 @@ export function triggerAutoSend(
inputEl.dispatchEvent(new Event("change", { bubbles: true }));
}

const action = AUTO_SEND_ACTIONS[retryCount] ?? "enter";
const action = getAutoSendAction(retryCount);
if (action === "ctrl-enter" || action === "enter") {
if (inputEl) {
const withCtrl = action === "ctrl-enter";
Expand Down
18 changes: 18 additions & 0 deletions bridge-browser/src/modules/auto_send_policy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export type AutoSendAction = "ctrl-enter" | "enter" | "button";

const AUTO_SEND_ACTIONS: readonly AutoSendAction[] = [
"enter",
"ctrl-enter",
"button",
"enter",
"ctrl-enter",
];
const AUTO_SEND_FILE_ATTEMPTS = 20;

export function getAutoSendAttemptLimit(hasFileUpload: boolean): number {
return hasFileUpload ? AUTO_SEND_FILE_ATTEMPTS : AUTO_SEND_ACTIONS.length;
}

export function getAutoSendAction(attemptIndex: number): AutoSendAction {
return AUTO_SEND_ACTIONS[attemptIndex % AUTO_SEND_ACTIONS.length] ?? "enter";
}
35 changes: 35 additions & 0 deletions bridge-browser/test/auto_send_policy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
getAutoSendAction,
getAutoSendAttemptLimit,
} from "../src/modules/auto_send_policy";

function main(): void {
runTest("keeps five attempts for text-only sends", () => {
assertEqual(getAutoSendAttemptLimit(false), 5, "text-only attempt limit changed");
});
runTest("allows twenty attempts after a file paste", () => {
assertEqual(getAutoSendAttemptLimit(true), 20, "file upload attempt limit was not extended");
});
runTest("repeats the fallback action sequence during extended retries", () => {
assertEqual(getAutoSendAction(2), "button", "initial button fallback changed");
assertEqual(getAutoSendAction(7), "button", "extended retries did not repeat the button fallback");
});
}

function runTest(name: string, test: () => void): void {
try {
test();
console.log(`PASS ${name}`);
} catch (error) {
console.error(`FAIL ${name}`);
throw error;
}
}

function assertEqual(actual: unknown, expected: unknown, message: string): void {
if (actual !== expected) {
throw new Error(`${message}: expected ${String(expected)}, received ${String(actual)}`);
}
}

main();
2 changes: 2 additions & 0 deletions bridge-browser/test/result_delivery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ async function main(): Promise<void> {
assertEqual(page.actions[2], "write", "result text was written before the attachment wait");
assert(page.input.innerText.includes('"status": "success"'), "acknowledged attachment became an error");
assert(delivery.delivered, "acknowledged result was not delivered");
assert(delivery.uploaded, "dispatched attachment was not reported to auto-send");
});
await runTest("reports an unacknowledged paste for only its attachment result", async () => {
const page = installFakePage(false);
Expand All @@ -30,6 +31,7 @@ async function main(): Promise<void> {
assert(page.input.innerText.includes('"name": "read_file"'), "unrelated result was lost");
assert(page.input.innerText.includes('"output": "text result"'), "unrelated result was changed");
assert(delivery.delivered, "attachment failure text did not remain sendable");
assert(delivery.uploaded, "unacknowledged attachment dispatch was not reported to auto-send");
});
await runTest("acknowledges each attachment group independently", async () => {
const page = installFakePage([true, false]);
Expand Down
Loading