fix: sync canonical kiro.rs settings for upload
This commit is contained in:
@@ -284,13 +284,6 @@
|
|||||||
await addLog(message, level, nodeId ? { nodeId } : {});
|
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 = {}) {
|
async function applyRuntimeState(currentState = {}, patch = {}) {
|
||||||
const nextPatch = mergeRuntimePatch(currentState, patch);
|
const nextPatch = mergeRuntimePatch(currentState, patch);
|
||||||
await setState(nextPatch);
|
await setState(nextPatch);
|
||||||
@@ -313,7 +306,7 @@
|
|||||||
|
|
||||||
async function executeKiroUploadCredential(state = {}) {
|
async function executeKiroUploadCredential(state = {}) {
|
||||||
const nodeId = String(state?.nodeId || 'kiro-upload-credential').trim();
|
const nodeId = String(state?.nodeId || 'kiro-upload-credential').trim();
|
||||||
const currentState = await getExecutionState(state);
|
const currentState = await getState();
|
||||||
try {
|
try {
|
||||||
const targetId = resolveKiroTargetId(currentState);
|
const targetId = resolveKiroTargetId(currentState);
|
||||||
const targetConfig = resolveKiroTargetConfig(currentState, targetId);
|
const targetConfig = resolveKiroTargetConfig(currentState, targetId);
|
||||||
|
|||||||
@@ -1430,21 +1430,21 @@
|
|||||||
|| phoneSignupReloginAfterBindEmailChanged;
|
|| phoneSignupReloginAfterBindEmailChanged;
|
||||||
const oauthFlowTimeoutDisabled = Object.prototype.hasOwnProperty.call(updates, 'oauthFlowTimeoutEnabled')
|
const oauthFlowTimeoutDisabled = Object.prototype.hasOwnProperty.call(updates, 'oauthFlowTimeoutEnabled')
|
||||||
&& updates.oauthFlowTimeoutEnabled === false;
|
&& updates.oauthFlowTimeoutEnabled === false;
|
||||||
await setPersistentSettings(updates);
|
const canonicalSettingsUpdates = await setPersistentSettings(updates);
|
||||||
const stateUpdates = {
|
const stateUpdates = {
|
||||||
...updates,
|
...canonicalSettingsUpdates,
|
||||||
...sessionUpdates,
|
...sessionUpdates,
|
||||||
...(oauthFlowTimeoutDisabled ? {
|
...(oauthFlowTimeoutDisabled ? {
|
||||||
oauthFlowDeadlineAt: null,
|
oauthFlowDeadlineAt: null,
|
||||||
oauthFlowDeadlineSourceUrl: null,
|
oauthFlowDeadlineSourceUrl: null,
|
||||||
} : {}),
|
} : {}),
|
||||||
};
|
};
|
||||||
if (Object.prototype.hasOwnProperty.call(updates, 'activeFlowId')
|
if (Object.prototype.hasOwnProperty.call(canonicalSettingsUpdates, 'activeFlowId')
|
||||||
&& !Object.prototype.hasOwnProperty.call(stateUpdates, 'flowId')) {
|
&& !Object.prototype.hasOwnProperty.call(stateUpdates, 'flowId')) {
|
||||||
stateUpdates.flowId = updates.activeFlowId;
|
stateUpdates.flowId = canonicalSettingsUpdates.activeFlowId;
|
||||||
}
|
}
|
||||||
if (Object.prototype.hasOwnProperty.call(updates, 'icloudHostPreference')) {
|
if (Object.prototype.hasOwnProperty.call(canonicalSettingsUpdates, 'icloudHostPreference')) {
|
||||||
const nextHostPreference = String(updates.icloudHostPreference || '').trim().toLowerCase();
|
const nextHostPreference = String(canonicalSettingsUpdates.icloudHostPreference || '').trim().toLowerCase();
|
||||||
stateUpdates.preferredIcloudHost = nextHostPreference === 'icloud.com' || nextHostPreference === 'icloud.com.cn'
|
stateUpdates.preferredIcloudHost = nextHostPreference === 'icloud.com' || nextHostPreference === 'icloud.com.cn'
|
||||||
? nextHostPreference
|
? 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.match(machineId, /^[0-9a-f]{64}$/);
|
||||||
assert.equal(Object.prototype.hasOwnProperty.call(payload, 'profileArn'), false);
|
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');
|
||||||
|
});
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ test('SAVE_SETTING broadcasts free phone reuse setting updates for realtime side
|
|||||||
},
|
},
|
||||||
broadcastDataUpdate: (payload) => broadcasts.push(payload),
|
broadcastDataUpdate: (payload) => broadcasts.push(payload),
|
||||||
getState: async () => ({ ...state }),
|
getState: async () => ({ ...state }),
|
||||||
setPersistentSettings: async () => {},
|
setPersistentSettings: async (updates) => ({ ...updates }),
|
||||||
setState: async (updates) => {
|
setState: async (updates) => {
|
||||||
state = { ...state, ...updates };
|
state = { ...state, ...updates };
|
||||||
},
|
},
|
||||||
@@ -181,6 +181,7 @@ test('SAVE_SETTING preserves phone reuse preferences while phone signup is selec
|
|||||||
getState: async () => ({ ...state }),
|
getState: async () => ({ ...state }),
|
||||||
setPersistentSettings: async (updates) => {
|
setPersistentSettings: async (updates) => {
|
||||||
persistedPayloads.push({ ...updates });
|
persistedPayloads.push({ ...updates });
|
||||||
|
return { ...updates };
|
||||||
},
|
},
|
||||||
setState: async (updates) => {
|
setState: async (updates) => {
|
||||||
state = { ...state, ...updates };
|
state = { ...state, ...updates };
|
||||||
@@ -239,7 +240,7 @@ test('SAVE_SETTING allows phone reuse preferences after switching back to email
|
|||||||
}),
|
}),
|
||||||
broadcastDataUpdate: () => {},
|
broadcastDataUpdate: () => {},
|
||||||
getState: async () => ({ ...state }),
|
getState: async () => ({ ...state }),
|
||||||
setPersistentSettings: async () => {},
|
setPersistentSettings: async (updates) => ({ ...updates }),
|
||||||
setState: async (updates) => {
|
setState: async (updates) => {
|
||||||
state = { ...state, ...updates };
|
state = { ...state, ...updates };
|
||||||
},
|
},
|
||||||
@@ -280,7 +281,7 @@ test('SAVE_SETTING broadcasts operation delay setting without background success
|
|||||||
: {},
|
: {},
|
||||||
broadcastDataUpdate: (payload) => broadcasts.push(payload),
|
broadcastDataUpdate: (payload) => broadcasts.push(payload),
|
||||||
getState: async () => ({ ...state }),
|
getState: async () => ({ ...state }),
|
||||||
setPersistentSettings: async () => {},
|
setPersistentSettings: async (updates) => ({ ...updates }),
|
||||||
setState: async (updates) => { state = { ...state, ...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),
|
broadcastDataUpdate: (payload) => broadcasts.push(payload),
|
||||||
getState: async () => ({ ...state }),
|
getState: async () => ({ ...state }),
|
||||||
setPersistentSettings: async () => {},
|
setPersistentSettings: async (updates) => ({ ...updates }),
|
||||||
setState: async (updates) => { state = { ...state, ...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 () => {
|
test('AUTO_RUN applies current flow selection from payload before starting loop', async () => {
|
||||||
const source = fs.readFileSync('background/message-router.js', 'utf8');
|
const source = fs.readFileSync('background/message-router.js', 'utf8');
|
||||||
const globalScope = { console };
|
const globalScope = { console };
|
||||||
@@ -435,7 +553,7 @@ test('SAVE_SETTING re-resolves signup method when panel mode changes', async ()
|
|||||||
broadcastDataUpdate: () => {},
|
broadcastDataUpdate: () => {},
|
||||||
getState: async () => ({ ...state }),
|
getState: async () => ({ ...state }),
|
||||||
resolveSignupMethod: (nextState = {}) => nextState.panelMode === 'cpa' ? 'email' : 'phone',
|
resolveSignupMethod: (nextState = {}) => nextState.panelMode === 'cpa' ? 'email' : 'phone',
|
||||||
setPersistentSettings: async () => {},
|
setPersistentSettings: async (updates) => ({ ...updates }),
|
||||||
setState: async (updates) => {
|
setState: async (updates) => {
|
||||||
state = { ...state, ...updates };
|
state = { ...state, ...updates };
|
||||||
},
|
},
|
||||||
@@ -479,6 +597,7 @@ test('SAVE_SETTING applies shared mode-switch normalization before persisting in
|
|||||||
),
|
),
|
||||||
setPersistentSettings: async (updates) => {
|
setPersistentSettings: async (updates) => {
|
||||||
persistedPayloads.push({ ...updates });
|
persistedPayloads.push({ ...updates });
|
||||||
|
return { ...updates };
|
||||||
},
|
},
|
||||||
setState: async (updates) => {
|
setState: async (updates) => {
|
||||||
state = { ...state, ...updates };
|
state = { ...state, ...updates };
|
||||||
|
|||||||
Reference in New Issue
Block a user