feat: advance browser agent integration workflows

This commit is contained in:
go0p
2026-08-06 15:11:35 +08:00
committed by go0p
parent af5a4db694
commit 0c8e1c7b69
215 changed files with 35137 additions and 5442 deletions
+117
View File
@@ -0,0 +1,117 @@
import { describe, expect, it } from 'vitest';
import { CONTROL_CAPABILITY_SCOPES } from '@/protocol/capabilities';
import type { ActiveTabInfo, ExtensionState } from '@/types/models';
import { authorizationShareGrantInput, gatewayShareActive, gatewayShareGrantInput } from './gateway-share';
const NOW = 1_000_000;
const tab: ActiveTabInfo = {
id: 7,
windowId: 1,
title: 'Login',
url: 'https://app.example.test/login',
incognito: false,
};
function state(): ExtensionState {
return {
version: 7,
} as ExtensionState;
}
describe('gateway quick share', () => {
it('creates a 30 minute control grant for the current main frame', () => {
const input = gatewayShareGrantInput(state(), tab, NOW);
expect(input.targets).toEqual([{ tabId: 7, frameId: 0 }]);
expect(input.durationMinutes).toBe(30);
expect(input.scopes).toEqual(expect.arrayContaining(CONTROL_CAPABILITY_SCOPES));
});
it('preserves an active session while adding the current tab and gateway capabilities', () => {
const current = state();
current.activeGrant = {
id: 'grant',
taskId: 'task',
createdAt: NOW - 10_000,
expiresAt: NOW + 60 * 60_000,
scopes: ['browser.tabs.read'],
targets: [{
tabId: 3,
frameId: 0,
documentId: 'document-a',
isolationContextId: 'profile:default',
origin: 'https://other.example.test',
grantedUrl: 'https://other.example.test/',
title: 'Other',
}],
};
const input = gatewayShareGrantInput(current, tab, NOW);
expect(input.targets).toEqual([
{ tabId: 3, frameId: 0 },
{ tabId: 7, frameId: 0 },
]);
expect(input.durationMinutes).toBe(60);
expect(input.taskId).toBe('task');
expect(current.activeGrant.scopes).toEqual(['browser.tabs.read']);
});
it('only reports ready when the tab, origin, lifetime and control scopes match', () => {
const current = state();
const input = gatewayShareGrantInput(current, tab, NOW);
const grant = {
id: 'grant',
taskId: 'task',
createdAt: NOW,
expiresAt: NOW + 30 * 60_000,
scopes: input.scopes,
targets: [{
tabId: tab.id,
frameId: 0,
documentId: 'document',
isolationContextId: 'profile:default',
origin: 'https://app.example.test',
grantedUrl: tab.url,
title: tab.title,
}],
};
expect(gatewayShareActive(grant, tab, NOW)).toBe(true);
expect(gatewayShareActive({ ...grant, expiresAt: NOW }, tab, NOW)).toBe(false);
expect(gatewayShareActive({ ...grant, scopes: ['browser.tabs.read'] }, tab, NOW)).toBe(false);
expect(gatewayShareActive(grant, { ...tab, url: 'https://elsewhere.example.test/' }, NOW)).toBe(false);
});
it('creates a focused two-tab authorization grant without retaining unrelated targets', () => {
const current = state();
current.activeGrant = {
id: 'grant',
taskId: 'existing-task',
createdAt: NOW - 1_000,
expiresAt: NOW + 45 * 60_000,
scopes: ['browser.tabs.read'],
targets: [{
tabId: 99,
frameId: 0,
documentId: 'unrelated',
isolationContextId: 'unrelated',
origin: 'https://other.example.test',
grantedUrl: 'https://other.example.test',
title: 'Unrelated',
}],
};
const right = { ...tab, id: 8, incognito: true };
const input = authorizationShareGrantInput(current, [tab, right], NOW);
expect(input.targets).toEqual([
{ tabId: 7, frameId: 0 },
{ tabId: 8, frameId: 0 },
]);
expect(input.scopes).toEqual(expect.arrayContaining(CONTROL_CAPABILITY_SCOPES));
expect(input.durationMinutes).toBe(45);
expect(input.taskId).toBe('existing-task');
});
});