feat(browser): add local handoff presentation

This commit is contained in:
go0p
2026-09-03 17:04:00 +08:00
parent 0a349a7928
commit 8e84735ecf
11 changed files with 536 additions and 26 deletions
@@ -2,16 +2,29 @@ import { browser } from 'wxt/browser';
import type { HandoffReason } from '@/types/models';
import type { CapabilityDomainHandler } from '../capability-context';
import { allowedTarget } from '../capability-context';
import { activateTab } from '@/platform/browser/targets';
import { getTab } from '@/platform/browser/targets';
import { getState, updateState } from '@/platform/storage/state';
import { setAgentRuntimeState } from '@/features/agent-runtime/service';
import { ExtensionError } from '@/shared/errors';
import { HANDOFF_CAPABILITY_DOMAIN } from '../capability-domains';
import { focusHandoff, getHandoffPresentation, resolveHandoff } from '@/features/handoff/service';
export const handoffCapabilityHandler: CapabilityDomainHandler = {
...HANDOFF_CAPABILITY_DOMAIN,
async handle({ method, input, grant }) {
if (method === 'browser.handoff.presentation.get') {
return getHandoffPresentation(String(input.handoffId || ''), grant);
}
if (method === 'browser.handoff.focus') {
return focusHandoff(String(input.handoffId || ''), grant);
}
if (method === 'browser.handoff.resolve') {
return resolveHandoff(
String(input.handoffId || ''),
input.outcome === 'cancelled' ? 'cancelled' : 'completed',
grant,
);
}
if (method === 'browser.handoff.status') {
const handoff = (await getState()).handoff;
return handoff?.taskId === grant.taskId ? handoff : { state: 'idle' };
@@ -50,7 +63,6 @@ export const handoffCapabilityHandler: CapabilityDomainHandler = {
},
};
});
await activateTab(resolvedTarget.tabId);
await browser.action.setBadgeBackgroundColor({ color: '#ee7815' });
await browser.action.setBadgeText({ text: '待确认', tabId: resolvedTarget.tabId });
await setAgentRuntimeState('waiting_for_human', grant);
@@ -14,6 +14,7 @@ import { listCookies } from '@/features/cookies/service';
import { resolveTabCookieStoreId } from '@/platform/browser/isolation';
import { ExtensionError } from '@/shared/errors';
import { PAGE_CAPABILITY_DOMAIN } from '../capability-domains';
import { getState } from '@/platform/storage/state';
export const pageCapabilityHandler: CapabilityDomainHandler = {
...PAGE_CAPABILITY_DOMAIN,
@@ -63,7 +64,12 @@ export const pageCapabilityHandler: CapabilityDomainHandler = {
await browser.action.setBadgeBackgroundColor({ color: '#f28c28' });
await browser.action.setBadgeText({ text: '接管', tabId: target.tabId });
globalThis.setTimeout(
() => void browser.action.setBadgeText({ text: '', tabId: target.tabId }),
() => void getState()
.then((state) => browser.action.setBadgeText({
text: state.bridge.managedInstance?.badge || '',
tabId: target.tabId,
}))
.catch(() => undefined),
10_000,
);
return { activated: true, target };