fix: sync canonical kiro.rs settings for upload

This commit is contained in:
QLHazyCoder
2026-05-19 01:30:28 +08:00
parent 99e5363539
commit 09319c20a9
4 changed files with 229 additions and 19 deletions
+1 -8
View File
@@ -284,13 +284,6 @@
await addLog(message, level, nodeId ? { nodeId } : {});
}
async function getExecutionState(state = {}) {
if (state && typeof state === 'object' && !Array.isArray(state) && Object.keys(state).length) {
return state;
}
return getState();
}
async function applyRuntimeState(currentState = {}, patch = {}) {
const nextPatch = mergeRuntimePatch(currentState, patch);
await setState(nextPatch);
@@ -313,7 +306,7 @@
async function executeKiroUploadCredential(state = {}) {
const nodeId = String(state?.nodeId || 'kiro-upload-credential').trim();
const currentState = await getExecutionState(state);
const currentState = await getState();
try {
const targetId = resolveKiroTargetId(currentState);
const targetConfig = resolveKiroTargetConfig(currentState, targetId);
+6 -6
View File
@@ -1430,21 +1430,21 @@
|| phoneSignupReloginAfterBindEmailChanged;
const oauthFlowTimeoutDisabled = Object.prototype.hasOwnProperty.call(updates, 'oauthFlowTimeoutEnabled')
&& updates.oauthFlowTimeoutEnabled === false;
await setPersistentSettings(updates);
const canonicalSettingsUpdates = await setPersistentSettings(updates);
const stateUpdates = {
...updates,
...canonicalSettingsUpdates,
...sessionUpdates,
...(oauthFlowTimeoutDisabled ? {
oauthFlowDeadlineAt: null,
oauthFlowDeadlineSourceUrl: null,
} : {}),
};
if (Object.prototype.hasOwnProperty.call(updates, 'activeFlowId')
if (Object.prototype.hasOwnProperty.call(canonicalSettingsUpdates, 'activeFlowId')
&& !Object.prototype.hasOwnProperty.call(stateUpdates, 'flowId')) {
stateUpdates.flowId = updates.activeFlowId;
stateUpdates.flowId = canonicalSettingsUpdates.activeFlowId;
}
if (Object.prototype.hasOwnProperty.call(updates, 'icloudHostPreference')) {
const nextHostPreference = String(updates.icloudHostPreference || '').trim().toLowerCase();
if (Object.prototype.hasOwnProperty.call(canonicalSettingsUpdates, 'icloudHostPreference')) {
const nextHostPreference = String(canonicalSettingsUpdates.icloudHostPreference || '').trim().toLowerCase();
stateUpdates.preferredIcloudHost = nextHostPreference === 'icloud.com' || nextHostPreference === 'icloud.com.cn'
? nextHostPreference
: '';
@@ -64,3 +64,101 @@ test('kiro publisher builds kiro.rs payload from desktop auth runtime without pr
assert.match(machineId, /^[0-9a-f]{64}$/);
assert.equal(Object.prototype.hasOwnProperty.call(payload, 'profileArn'), false);
});
test('kiro publisher reads latest kiro.rs key from background state instead of stale node snapshot', async () => {
const api = loadPublisherApi();
const requests = [];
let liveState = {
kiroTargetId: 'kiro-rs',
kiroRsUrl: 'https://kiro.example.com/admin',
kiroRsKey: 'live-key',
email: 'aws-user@example.com',
kiroRuntime: {
register: {
email: 'aws-user@example.com',
},
desktopAuth: {
region: 'us-east-1',
clientId: 'client-001',
clientSecret: 'secret-001',
refreshToken: 'refresh-token-001',
},
upload: {
targetId: 'kiro-rs',
},
},
settingsState: {
flows: {
kiro: {
targetId: 'kiro-rs',
targets: {
'kiro-rs': {
baseUrl: 'https://kiro.example.com/admin',
apiKey: 'live-key',
},
},
},
},
},
};
const completed = [];
const publisher = api.createKiroRsPublisher({
addLog: async () => {},
completeNodeFromBackground: async (nodeId, payload) => {
completed.push({ nodeId, payload });
},
fetchImpl: async (url, options = {}) => {
requests.push({
url,
method: options.method || 'GET',
apiKey: options.headers?.['x-api-key'],
});
if ((options.method || 'GET') === 'GET') {
return {
ok: true,
status: 200,
statusText: 'OK',
text: async () => JSON.stringify({ items: [] }),
};
}
return {
ok: true,
status: 200,
statusText: 'OK',
text: async () => JSON.stringify({
message: 'Credential uploaded.',
credentialId: 9,
email: 'aws-user@example.com',
}),
};
},
getState: async () => ({ ...liveState }),
setState: async (updates = {}) => {
liveState = { ...liveState, ...updates };
},
});
await publisher.executeKiroUploadCredential({
nodeId: 'kiro-upload-credential',
kiroRsKey: '',
settingsState: {
flows: {
kiro: {
targetId: 'kiro-rs',
targets: {
'kiro-rs': {
baseUrl: 'https://kiro.example.com/admin',
apiKey: '',
},
},
},
},
},
});
assert.equal(requests.length, 2);
assert.equal(requests[0].apiKey, 'live-key');
assert.equal(requests[1].apiKey, 'live-key');
assert.equal(completed.length, 1);
assert.equal(completed[0].nodeId, 'kiro-upload-credential');
});
+124 -5
View File
@@ -120,7 +120,7 @@ test('SAVE_SETTING broadcasts free phone reuse setting updates for realtime side
},
broadcastDataUpdate: (payload) => broadcasts.push(payload),
getState: async () => ({ ...state }),
setPersistentSettings: async () => {},
setPersistentSettings: async (updates) => ({ ...updates }),
setState: async (updates) => {
state = { ...state, ...updates };
},
@@ -181,6 +181,7 @@ test('SAVE_SETTING preserves phone reuse preferences while phone signup is selec
getState: async () => ({ ...state }),
setPersistentSettings: async (updates) => {
persistedPayloads.push({ ...updates });
return { ...updates };
},
setState: async (updates) => {
state = { ...state, ...updates };
@@ -239,7 +240,7 @@ test('SAVE_SETTING allows phone reuse preferences after switching back to email
}),
broadcastDataUpdate: () => {},
getState: async () => ({ ...state }),
setPersistentSettings: async () => {},
setPersistentSettings: async (updates) => ({ ...updates }),
setState: async (updates) => {
state = { ...state, ...updates };
},
@@ -280,7 +281,7 @@ test('SAVE_SETTING broadcasts operation delay setting without background success
: {},
broadcastDataUpdate: (payload) => broadcasts.push(payload),
getState: async () => ({ ...state }),
setPersistentSettings: async () => {},
setPersistentSettings: async (updates) => ({ ...updates }),
setState: async (updates) => { state = { ...state, ...updates }; },
});
@@ -311,7 +312,7 @@ test('SAVE_SETTING mirrors activeFlowId into flowId when switching to kiro flow'
: {},
broadcastDataUpdate: (payload) => broadcasts.push(payload),
getState: async () => ({ ...state }),
setPersistentSettings: async () => {},
setPersistentSettings: async (updates) => ({ ...updates }),
setState: async (updates) => { state = { ...state, ...updates }; },
});
@@ -331,6 +332,123 @@ test('SAVE_SETTING mirrors activeFlowId into flowId when switching to kiro flow'
});
});
test('SAVE_SETTING syncs canonical kiro settingsState back into session state', async () => {
const source = fs.readFileSync('background/message-router.js', 'utf8');
const globalScope = { console };
const api = new Function('self', `${source}; return self.MultiPageBackgroundMessageRouter;`)(globalScope);
const canonicalSettingsState = {
schemaVersion: 4,
activeFlowId: 'kiro',
services: {
account: { customPassword: '' },
email: { provider: 'duck' },
proxy: { enabled: false, provider: '711proxy', mode: 'account' },
},
flows: {
openai: {
integrationTargetId: 'cpa',
integrationTargets: {
cpa: { vpsUrl: '', vpsPassword: '', localCpaStep9Mode: 'submit' },
sub2api: {
sub2apiUrl: '',
sub2apiEmail: '',
sub2apiPassword: '',
sub2apiGroupName: 'codex',
sub2apiGroupNames: ['codex', 'openai-plus'],
sub2apiAccountPriority: 1,
sub2apiDefaultProxyName: '',
},
codex2api: { codex2apiUrl: '', codex2apiAdminKey: '' },
},
signup: {
signupMethod: 'email',
phoneVerificationEnabled: false,
phoneSignupReloginAfterBindEmailEnabled: false,
},
plus: {
plusModeEnabled: false,
plusPaymentMethod: 'paypal',
},
autoRun: {
stepExecutionRange: { enabled: false, fromStep: 1, toStep: 11 },
},
},
kiro: {
targetId: 'kiro-rs',
targets: {
'kiro-rs': {
baseUrl: 'https://kiro.example.com/admin',
apiKey: 'live-key',
},
},
autoRun: {
stepExecutionRange: { enabled: false, fromStep: 1, toStep: 9 },
},
},
},
};
let state = {
activeFlowId: 'kiro',
flowId: 'kiro',
kiroTargetId: 'kiro-rs',
kiroRsUrl: 'https://kiro.example.com/admin',
kiroRsKey: '',
settingsSchemaVersion: 4,
settingsState: {
...canonicalSettingsState,
flows: {
...canonicalSettingsState.flows,
kiro: {
...canonicalSettingsState.flows.kiro,
targets: {
'kiro-rs': {
baseUrl: 'https://kiro.example.com/admin',
apiKey: '',
},
},
},
},
},
plusModeEnabled: false,
plusPaymentMethod: 'paypal',
};
const router = api.createMessageRouter({
addLog: async () => {},
buildLuckmailSessionSettingsPayload: () => ({}),
buildPersistentSettingsPayload: (input = {}) => ({
activeFlowId: String(input.activeFlowId || 'kiro'),
kiroRsKey: String(input.kiroRsKey || ''),
}),
broadcastDataUpdate: () => {},
getState: async () => ({ ...state }),
setPersistentSettings: async () => ({
activeFlowId: 'kiro',
flowId: 'kiro',
kiroTargetId: 'kiro-rs',
kiroRsUrl: 'https://kiro.example.com/admin',
kiroRsKey: 'live-key',
settingsSchemaVersion: 4,
settingsState: canonicalSettingsState,
}),
setState: async (updates) => {
state = { ...state, ...updates };
},
});
const response = await router.handleMessage({
type: 'SAVE_SETTING',
payload: {
activeFlowId: 'kiro',
kiroRsKey: 'live-key',
},
});
assert.equal(response.ok, true);
assert.equal(state.kiroRsKey, 'live-key');
assert.equal(state.settingsState.flows.kiro.targets['kiro-rs'].apiKey, 'live-key');
});
test('AUTO_RUN applies current flow selection from payload before starting loop', async () => {
const source = fs.readFileSync('background/message-router.js', 'utf8');
const globalScope = { console };
@@ -435,7 +553,7 @@ test('SAVE_SETTING re-resolves signup method when panel mode changes', async ()
broadcastDataUpdate: () => {},
getState: async () => ({ ...state }),
resolveSignupMethod: (nextState = {}) => nextState.panelMode === 'cpa' ? 'email' : 'phone',
setPersistentSettings: async () => {},
setPersistentSettings: async (updates) => ({ ...updates }),
setState: async (updates) => {
state = { ...state, ...updates };
},
@@ -479,6 +597,7 @@ test('SAVE_SETTING applies shared mode-switch normalization before persisting in
),
setPersistentSettings: async (updates) => {
persistedPayloads.push({ ...updates });
return { ...updates };
},
setState: async (updates) => {
state = { ...state, ...updates };