重构多 flow 邮件轮询并接入 Grok SSO

This commit is contained in:
QLHazyCoder
2026-05-23 04:29:37 +08:00
parent 5610262f7d
commit 2ea9ad978e
37 changed files with 4345 additions and 843 deletions
@@ -2,10 +2,13 @@ const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
test('background imports mail rule registry and OpenAI mail rules modules', () => {
test('background imports mail rule registry and flow mail rules modules', () => {
const source = fs.readFileSync('background.js', 'utf8');
assert.match(source, /background\/mail-rule-registry\.js/);
assert.match(source, /flows\/openai\/mail-rules\.js/);
assert.match(source, /flows\/kiro\/mail-rules\.js/);
assert.match(source, /flows\/grok\/mail-rules\.js/);
assert.match(source, /background\/flow-mail-polling\.js/);
});
test('mail rule registry exposes canonical OpenAI verification poll payloads', () => {
@@ -133,3 +136,185 @@ test('mail rule registry rejects unknown active flow ids instead of silently usi
/未找到 flow=site-a 的邮件轮询规则构造器/
);
});
test('mail rule registry exposes Kiro AWS verification poll payloads by node', () => {
const stateSource = fs.readFileSync('flows/kiro/background/state.js', 'utf8');
const registrySource = fs.readFileSync('background/mail-rule-registry.js', 'utf8');
const kiroSource = fs.readFileSync('flows/kiro/mail-rules.js', 'utf8');
const globalScope = {};
new Function('self', `${stateSource}; ${registrySource}; ${kiroSource}; return self;`)(globalScope);
const kiroMailRules = globalScope.MultiPageKiroMailRules.createKiroMailRules({
LUCKMAIL_PROVIDER: 'luckmail-api',
MAIL_2925_VERIFICATION_INTERVAL_MS: 16000,
MAIL_2925_VERIFICATION_MAX_ATTEMPTS: 17,
});
const registry = globalScope.MultiPageBackgroundMailRuleRegistry.createMailRuleRegistry({
defaultFlowId: 'openai',
flowBuilders: {
kiro: kiroMailRules,
},
});
const baseState = {
activeFlowId: 'kiro',
mailProvider: '2925',
mail2925Mode: 'receive',
runtimeState: {
flowState: {
kiro: {
register: {
email: 'kiro-user@example.com',
},
},
},
},
};
assert.deepEqual(
registry.buildVerificationPollPayloadForNode(
'kiro-submit-verification-code',
baseState,
{ filterAfterTimestamp: 12345 }
),
{
flowId: 'kiro',
ruleId: 'kiro-submit-verification-code',
nodeId: 'kiro-submit-verification-code',
step: 4,
artifactType: 'code',
codePatterns: [
{
source: '(?:verification\\s*code|验证码|Your code is|code is)[:\\s]*(\\d{6})',
flags: 'gi',
},
{
source: '^\\s*(\\d{6})\\s*$',
flags: 'gm',
},
{
source: '>\\s*(\\d{6})\\s*<',
flags: 'g',
},
],
filterAfterTimestamp: 12345,
requiredKeywords: ['verification', '验证码', 'code', 'aws'],
senderFilters: [
'no-reply@signin.aws',
'no-reply@login.awsapps.com',
'noreply@amazon.com',
'account-update@amazon.com',
'no-reply@aws.amazon.com',
'noreply@aws.amazon.com',
'aws',
],
subjectFilters: ['aws builder id', 'verification', '验证码', 'code', 'aws'],
targetEmail: 'kiro-user@example.com',
targetEmailHints: ['kiro-user@example.com'],
mail2925MatchTargetEmail: true,
maxAttempts: 17,
intervalMs: 16000,
}
);
const desktopPayload = registry.buildVerificationPollPayloadForNode(
'kiro-complete-desktop-authorize',
{
...baseState,
mailProvider: 'luckmail-api',
mail2925Mode: 'provide',
}
);
assert.equal(desktopPayload.ruleId, 'kiro-complete-desktop-authorize');
assert.equal(desktopPayload.step, 8);
assert.equal(desktopPayload.mail2925MatchTargetEmail, false);
assert.equal(desktopPayload.maxAttempts, 3);
assert.equal(desktopPayload.intervalMs, 15000);
});
test('mail rule registry exposes Grok xAI verification poll payloads by node', () => {
const stateSource = fs.readFileSync('flows/grok/background/state.js', 'utf8');
const registrySource = fs.readFileSync('background/mail-rule-registry.js', 'utf8');
const grokSource = fs.readFileSync('flows/grok/mail-rules.js', 'utf8');
const globalScope = {};
new Function('self', `${stateSource}; ${registrySource}; ${grokSource}; return self;`)(globalScope);
const grokMailRules = globalScope.MultiPageGrokMailRules.createGrokMailRules({
LUCKMAIL_PROVIDER: 'luckmail-api',
MAIL_2925_VERIFICATION_INTERVAL_MS: 16000,
MAIL_2925_VERIFICATION_MAX_ATTEMPTS: 17,
});
const registry = globalScope.MultiPageBackgroundMailRuleRegistry.createMailRuleRegistry({
defaultFlowId: 'openai',
flowBuilders: {
grok: grokMailRules,
},
});
assert.deepEqual(
registry.buildVerificationPollPayloadForNode(
'grok-submit-verification-code',
{
activeFlowId: 'grok',
mailProvider: '2925',
mail2925Mode: 'receive',
runtimeState: {
flowState: {
grok: {
register: {
email: 'grok-user@example.com',
},
},
},
},
},
{ filterAfterTimestamp: 12345 }
),
{
flowId: 'grok',
ruleId: 'grok-submit-verification-code',
nodeId: 'grok-submit-verification-code',
step: 3,
artifactType: 'code',
codePatterns: [
{
source: '\\b([A-Z0-9]{3}-[A-Z0-9]{3})\\b',
flags: 'gi',
},
{
source: '(?:verification\\s*code|confirmation\\s*code|code\\s*is)[:\\s]*(\\d{6})',
flags: 'gi',
},
{
source: '(?:验证码|代码|确认码)[:\\s为]+(\\d{6})',
flags: 'gi',
},
{
source: '(?<!#)\\b(\\d{6})\\b',
flags: 'g',
},
],
filterAfterTimestamp: 12345,
requiredKeywords: ['xai', 'x.ai', 'grok', 'verification', 'confirmation', 'code', '验证码', '确认码'],
senderFilters: ['x.ai', 'xai', 'grok'],
subjectFilters: ['xai', 'x.ai', 'grok', 'verification', 'confirmation', 'code', '验证码', '确认码'],
targetEmail: 'grok-user@example.com',
targetEmailHints: ['grok-user@example.com'],
mail2925MatchTargetEmail: true,
maxAttempts: 17,
intervalMs: 16000,
}
);
const luckmailPayload = registry.buildVerificationPollPayloadForNode(
'grok-submit-verification-code',
{
activeFlowId: 'grok',
mailProvider: 'luckmail-api',
mail2925Mode: 'provide',
grokEmail: 'fallback@example.com',
}
);
assert.equal(luckmailPayload.mail2925MatchTargetEmail, false);
assert.equal(luckmailPayload.maxAttempts, 3);
assert.equal(luckmailPayload.intervalMs, 15000);
});