重构 Grok SSO 上传到 webchat2api
This commit is contained in:
@@ -0,0 +1,311 @@
|
||||
(function attachBackgroundGrokPublisherWebchat2Api(root, factory) {
|
||||
root.MultiPageBackgroundGrokPublisherWebchat2Api = factory(root);
|
||||
})(typeof self !== 'undefined' ? self : globalThis, function createBackgroundGrokPublisherWebchat2ApiModule(root) {
|
||||
const grokStateApi = root?.MultiPageBackgroundGrokState || null;
|
||||
const WEBCHAT2API_INJECT_PATH = '/api/remote-account/inject';
|
||||
const DEFAULT_SOURCE_ID = 'flowpilot-grok-sso';
|
||||
const DEFAULT_SOURCE_NAME = 'FlowPilot Grok SSO';
|
||||
|
||||
function isPlainObject(value) {
|
||||
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function cloneValue(value) {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((entry) => cloneValue(entry));
|
||||
}
|
||||
if (isPlainObject(value)) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(value).map(([key, entryValue]) => [key, cloneValue(entryValue)])
|
||||
);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function deepMerge(baseValue, patchValue) {
|
||||
if (Array.isArray(patchValue)) {
|
||||
return patchValue.map((entry) => cloneValue(entry));
|
||||
}
|
||||
if (!isPlainObject(patchValue)) {
|
||||
return patchValue === undefined ? cloneValue(baseValue) : patchValue;
|
||||
}
|
||||
|
||||
const baseObject = isPlainObject(baseValue) ? baseValue : {};
|
||||
const next = {
|
||||
...cloneValue(baseObject),
|
||||
};
|
||||
Object.entries(patchValue).forEach(([key, value]) => {
|
||||
next[key] = deepMerge(baseObject[key], value);
|
||||
});
|
||||
return next;
|
||||
}
|
||||
|
||||
function cleanString(value = '') {
|
||||
return String(value ?? '').trim();
|
||||
}
|
||||
|
||||
function getErrorMessage(error) {
|
||||
return error instanceof Error ? error.message : cleanString(error) || '未知错误';
|
||||
}
|
||||
|
||||
async function readResponse(response) {
|
||||
const text = await response.text();
|
||||
let json = null;
|
||||
try {
|
||||
json = text ? JSON.parse(text) : null;
|
||||
} catch (_error) {
|
||||
json = null;
|
||||
}
|
||||
return { text, json };
|
||||
}
|
||||
|
||||
function readWebchat2ApiResponseMessage(body = {}, fallback = '') {
|
||||
return cleanString(
|
||||
body?.json?.error?.message
|
||||
|| body?.json?.error
|
||||
|| body?.json?.message
|
||||
|| fallback
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeWebchat2ApiBaseUrl(value = '') {
|
||||
const rawUrl = cleanString(value);
|
||||
if (!rawUrl) {
|
||||
throw new Error('缺少 webchat2api 地址。');
|
||||
}
|
||||
const withProtocol = /^https?:\/\//i.test(rawUrl) ? rawUrl : `http://${rawUrl}`;
|
||||
let parsed = null;
|
||||
try {
|
||||
parsed = new URL(withProtocol);
|
||||
} catch (_error) {
|
||||
throw new Error('webchat2api 地址格式无效,请检查配置。');
|
||||
}
|
||||
if (!/^https?:$/.test(parsed.protocol)) {
|
||||
throw new Error('webchat2api 地址只支持 http 或 https。');
|
||||
}
|
||||
return parsed.origin;
|
||||
}
|
||||
|
||||
function buildWebchat2ApiInjectUrl(value = '') {
|
||||
return `${normalizeWebchat2ApiBaseUrl(value)}${WEBCHAT2API_INJECT_PATH}`;
|
||||
}
|
||||
|
||||
function normalizeWebchat2ApiAdminKey(value = '') {
|
||||
return cleanString(value);
|
||||
}
|
||||
|
||||
function readGrokRuntime(state = {}) {
|
||||
return grokStateApi?.ensureRuntimeState
|
||||
? grokStateApi.ensureRuntimeState(state)
|
||||
: (isPlainObject(state?.runtimeState?.flowState?.grok)
|
||||
? state.runtimeState.flowState.grok
|
||||
: (isPlainObject(state?.flowState?.grok) ? state.flowState.grok : {}));
|
||||
}
|
||||
|
||||
function buildCanonicalRuntimePatch(currentState = {}, nextRuntimeState = {}) {
|
||||
if (typeof grokStateApi?.buildRuntimeStatePatch === 'function') {
|
||||
return grokStateApi.buildRuntimeStatePatch(currentState, nextRuntimeState);
|
||||
}
|
||||
const baseRuntimeState = isPlainObject(currentState?.runtimeState)
|
||||
? cloneValue(currentState.runtimeState)
|
||||
: {};
|
||||
const baseFlowState = isPlainObject(baseRuntimeState.flowState)
|
||||
? cloneValue(baseRuntimeState.flowState)
|
||||
: {};
|
||||
return {
|
||||
runtimeState: {
|
||||
...baseRuntimeState,
|
||||
flowState: {
|
||||
...baseFlowState,
|
||||
grok: deepMerge(readGrokRuntime(currentState), nextRuntimeState),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function mergeRuntimePatch(currentState = {}, patch = {}) {
|
||||
return buildCanonicalRuntimePatch(
|
||||
currentState,
|
||||
deepMerge(readGrokRuntime(currentState), patch)
|
||||
);
|
||||
}
|
||||
|
||||
function resolveGrokWebchat2ApiConfig(state = {}) {
|
||||
const nestedConfig = state?.settingsState?.flows?.grok?.targets?.webchat2api || {};
|
||||
return {
|
||||
baseUrl: cleanString(nestedConfig.baseUrl || state?.grokWebchat2ApiUrl),
|
||||
apiKey: normalizeWebchat2ApiAdminKey(nestedConfig.apiKey ?? state?.grokWebchat2ApiAdminKey ?? ''),
|
||||
};
|
||||
}
|
||||
|
||||
function resolveGrokSsoCookie(state = {}) {
|
||||
const runtimeState = readGrokRuntime(state);
|
||||
return cleanString(runtimeState?.sso?.currentCookie || state?.grokSsoCookie);
|
||||
}
|
||||
|
||||
function buildGrokSsoInjectPayload(ssoCookie = '') {
|
||||
const normalizedCookie = cleanString(ssoCookie);
|
||||
if (!normalizedCookie) {
|
||||
throw new Error('缺少 Grok SSO Cookie,请先完成步骤 5。');
|
||||
}
|
||||
return {
|
||||
accounts: [{
|
||||
token: normalizedCookie,
|
||||
provider: 'grok',
|
||||
type: 'sso',
|
||||
}],
|
||||
strategy: 'merge',
|
||||
source_id: DEFAULT_SOURCE_ID,
|
||||
source_name: DEFAULT_SOURCE_NAME,
|
||||
provider: 'grok',
|
||||
};
|
||||
}
|
||||
|
||||
async function uploadGrokSsoToWebchat2Api(baseUrl, apiKey, ssoCookie, fetchImpl) {
|
||||
const endpointUrl = buildWebchat2ApiInjectUrl(baseUrl);
|
||||
const normalizedApiKey = normalizeWebchat2ApiAdminKey(apiKey);
|
||||
if (!normalizedApiKey) {
|
||||
throw new Error('缺少 webchat2api 管理密钥。');
|
||||
}
|
||||
|
||||
const response = await fetchImpl(endpointUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${normalizedApiKey}`,
|
||||
},
|
||||
body: JSON.stringify(buildGrokSsoInjectPayload(ssoCookie)),
|
||||
});
|
||||
const body = await readResponse(response);
|
||||
if (!response.ok) {
|
||||
const message = readWebchat2ApiResponseMessage(body, response.statusText) || `HTTP ${response.status}`;
|
||||
throw new Error(`webchat2api SSO 上传失败:${message}`);
|
||||
}
|
||||
if (isPlainObject(body.json) && Object.prototype.hasOwnProperty.call(body.json, 'code') && Number(body.json.code) !== 0) {
|
||||
const message = readWebchat2ApiResponseMessage(body, `code=${body.json.code}`);
|
||||
throw new Error(`webchat2api SSO 上传失败:${message}`);
|
||||
}
|
||||
return {
|
||||
endpointUrl,
|
||||
message: readWebchat2ApiResponseMessage(body, '') || '上传成功',
|
||||
raw: body.json,
|
||||
};
|
||||
}
|
||||
|
||||
function createGrokWebchat2ApiPublisher(deps = {}) {
|
||||
const {
|
||||
addLog = async () => {},
|
||||
completeNodeFromBackground,
|
||||
fetchImpl = typeof fetch === 'function' ? fetch.bind(globalThis) : null,
|
||||
getState = async () => ({}),
|
||||
setState = async () => {},
|
||||
} = deps;
|
||||
|
||||
if (typeof completeNodeFromBackground !== 'function') {
|
||||
throw new Error('Grok webchat2api publisher requires completeNodeFromBackground.');
|
||||
}
|
||||
if (typeof fetchImpl !== 'function') {
|
||||
throw new Error('Grok webchat2api publisher requires fetch support.');
|
||||
}
|
||||
|
||||
async function log(message, level = 'info', nodeId = '') {
|
||||
await addLog(message, level, nodeId ? { nodeId } : {});
|
||||
}
|
||||
|
||||
async function applyRuntimeState(currentState = {}, patch = {}) {
|
||||
const nextPatch = mergeRuntimePatch(currentState, patch);
|
||||
await setState(nextPatch);
|
||||
return nextPatch;
|
||||
}
|
||||
|
||||
async function persistFailure(currentState = {}, message = '', targetUrl = '') {
|
||||
const uploadPatch = {
|
||||
status: 'error',
|
||||
uploadedAt: 0,
|
||||
message,
|
||||
};
|
||||
const normalizedTargetUrl = cleanString(targetUrl);
|
||||
if (normalizedTargetUrl) {
|
||||
uploadPatch.targetUrl = normalizedTargetUrl;
|
||||
}
|
||||
const nextPatch = mergeRuntimePatch(currentState, {
|
||||
session: {
|
||||
lastError: message,
|
||||
},
|
||||
upload: uploadPatch,
|
||||
});
|
||||
await setState(nextPatch);
|
||||
}
|
||||
|
||||
async function executeGrokUploadSsoToWebchat2Api(state = {}) {
|
||||
const nodeId = cleanString(state?.nodeId) || 'grok-upload-sso-to-webchat2api';
|
||||
const currentState = await getState();
|
||||
let failureTargetUrl = '';
|
||||
try {
|
||||
const targetConfig = resolveGrokWebchat2ApiConfig(currentState);
|
||||
const endpointUrl = buildWebchat2ApiInjectUrl(targetConfig.baseUrl);
|
||||
failureTargetUrl = endpointUrl;
|
||||
const apiKey = normalizeWebchat2ApiAdminKey(targetConfig.apiKey);
|
||||
if (!apiKey) {
|
||||
throw new Error('缺少 webchat2api 管理密钥。');
|
||||
}
|
||||
const ssoCookie = resolveGrokSsoCookie(currentState);
|
||||
if (!ssoCookie) {
|
||||
throw new Error('缺少 Grok SSO Cookie,请先完成步骤 5。');
|
||||
}
|
||||
|
||||
await applyRuntimeState(currentState, {
|
||||
session: {
|
||||
lastError: '',
|
||||
},
|
||||
upload: {
|
||||
status: 'uploading',
|
||||
uploadedAt: 0,
|
||||
message: '',
|
||||
targetUrl: endpointUrl,
|
||||
},
|
||||
});
|
||||
|
||||
await log('步骤 6:正在上传 Grok SSO 到 webchat2api...', 'info', nodeId);
|
||||
const uploadResult = await uploadGrokSsoToWebchat2Api(
|
||||
targetConfig.baseUrl,
|
||||
apiKey,
|
||||
ssoCookie,
|
||||
fetchImpl
|
||||
);
|
||||
const uploadedAt = Date.now();
|
||||
const payload = await applyRuntimeState(currentState, {
|
||||
session: {
|
||||
lastError: '',
|
||||
},
|
||||
upload: {
|
||||
status: 'uploaded',
|
||||
uploadedAt,
|
||||
message: uploadResult.message || '上传成功',
|
||||
targetUrl: uploadResult.endpointUrl,
|
||||
},
|
||||
});
|
||||
await log(`步骤 6:Grok SSO 已上传到 webchat2api,状态:${uploadResult.message || '上传成功'}。`, 'ok', nodeId);
|
||||
await completeNodeFromBackground(nodeId, payload);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
await persistFailure(currentState, message, failureTargetUrl);
|
||||
await log(`步骤 6:${message}`, 'error', nodeId);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
executeGrokUploadSsoToWebchat2Api,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
buildGrokSsoInjectPayload,
|
||||
buildWebchat2ApiInjectUrl,
|
||||
createGrokWebchat2ApiPublisher,
|
||||
normalizeWebchat2ApiBaseUrl,
|
||||
uploadGrokSsoToWebchat2Api,
|
||||
};
|
||||
});
|
||||
@@ -613,22 +613,17 @@
|
||||
throw new Error('未找到 x.ai/grok sso Cookie。');
|
||||
}
|
||||
|
||||
const latestState = await getState();
|
||||
const existingSsoCookies = Array.isArray(latestState?.grokSsoCookies)
|
||||
? latestState.grokSsoCookies
|
||||
.map((entry) => cleanString(entry))
|
||||
.filter(Boolean)
|
||||
: [];
|
||||
const nextSsoCookies = existingSsoCookies.includes(ssoCookie)
|
||||
? existingSsoCookies
|
||||
: [...existingSsoCookies, ssoCookie];
|
||||
const completedAt = Date.now();
|
||||
const completionPatch = {
|
||||
grokSsoCookie: ssoCookie,
|
||||
grokSsoCookies: nextSsoCookies,
|
||||
grokSsoCookies: [ssoCookie],
|
||||
grokSsoExtractedAt: completedAt,
|
||||
grokCompletedAt: completedAt,
|
||||
grokRegisterStatus: 'completed',
|
||||
grokWebchat2ApiUploadStatus: '',
|
||||
grokWebchat2ApiUploadedAt: 0,
|
||||
grokWebchat2ApiUploadMessage: '',
|
||||
grokWebchat2ApiTargetUrl: '',
|
||||
...buildGrokRuntimePatch({
|
||||
register: {
|
||||
status: 'completed',
|
||||
@@ -636,9 +631,15 @@
|
||||
},
|
||||
sso: {
|
||||
currentCookie: ssoCookie,
|
||||
cookies: nextSsoCookies,
|
||||
cookies: [ssoCookie],
|
||||
extractedAt: completedAt,
|
||||
},
|
||||
upload: {
|
||||
status: '',
|
||||
uploadedAt: 0,
|
||||
message: '',
|
||||
targetUrl: '',
|
||||
},
|
||||
session: {
|
||||
lastError: '',
|
||||
},
|
||||
|
||||
@@ -39,6 +39,26 @@
|
||||
return String(value ?? '').trim();
|
||||
}
|
||||
|
||||
function assignCleanString(target = {}, key = '', value = '') {
|
||||
const normalized = cleanString(value);
|
||||
if (normalized) {
|
||||
target[key] = normalized;
|
||||
}
|
||||
}
|
||||
|
||||
function assignPositiveInteger(target = {}, key = '', value) {
|
||||
const numeric = Math.floor(Number(value));
|
||||
if (Number.isInteger(numeric) && numeric > 0) {
|
||||
target[key] = numeric;
|
||||
}
|
||||
}
|
||||
|
||||
function assignNonEmptyArray(target = {}, key = '', value) {
|
||||
if (Array.isArray(value) && value.length) {
|
||||
target[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeInteger(value, fallback = 0) {
|
||||
const numeric = Math.floor(Number(value));
|
||||
return Number.isInteger(numeric) ? numeric : fallback;
|
||||
@@ -87,6 +107,12 @@
|
||||
cookies: [],
|
||||
extractedAt: 0,
|
||||
},
|
||||
upload: {
|
||||
status: '',
|
||||
uploadedAt: 0,
|
||||
message: '',
|
||||
targetUrl: '',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -115,6 +141,12 @@
|
||||
cookies: normalizeSsoCookies(merged.sso?.cookies || merged.ssoCookies),
|
||||
extractedAt: Math.max(0, normalizeInteger(merged.sso?.extractedAt)),
|
||||
},
|
||||
upload: {
|
||||
status: cleanString(merged.upload?.status),
|
||||
uploadedAt: Math.max(0, normalizeInteger(merged.upload?.uploadedAt)),
|
||||
message: cleanString(merged.upload?.message),
|
||||
targetUrl: cleanString(merged.upload?.targetUrl),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -152,6 +184,10 @@
|
||||
grokSsoCookie: normalizedRuntimeState.sso.currentCookie,
|
||||
grokSsoCookies: normalizedRuntimeState.sso.cookies,
|
||||
grokSsoExtractedAt: normalizedRuntimeState.sso.extractedAt,
|
||||
grokWebchat2ApiUploadStatus: normalizedRuntimeState.upload.status,
|
||||
grokWebchat2ApiUploadedAt: normalizedRuntimeState.upload.uploadedAt,
|
||||
grokWebchat2ApiUploadMessage: normalizedRuntimeState.upload.message,
|
||||
grokWebchat2ApiTargetUrl: normalizedRuntimeState.upload.targetUrl,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -163,27 +199,29 @@
|
||||
? state.flowState.grok
|
||||
: {};
|
||||
const flatRuntime = {
|
||||
session: {
|
||||
registerTabId: state.grokRegisterTabId,
|
||||
pageState: state.grokPageState,
|
||||
pageUrl: state.grokPageUrl || state.grokPostVerificationUrl,
|
||||
},
|
||||
register: {
|
||||
email: state.grokEmail || state.email,
|
||||
firstName: state.grokFirstName,
|
||||
lastName: state.grokLastName,
|
||||
password: state.grokPassword,
|
||||
verificationRequestedAt: state.grokVerificationRequestedAt,
|
||||
verificationCode: state.grokVerificationCode,
|
||||
status: state.grokRegisterStatus,
|
||||
completedAt: state.grokCompletedAt,
|
||||
},
|
||||
sso: {
|
||||
currentCookie: state.grokSsoCookie,
|
||||
cookies: state.grokSsoCookies,
|
||||
extractedAt: state.grokSsoExtractedAt || state.grokCompletedAt,
|
||||
},
|
||||
session: {},
|
||||
register: {},
|
||||
sso: {},
|
||||
upload: {},
|
||||
};
|
||||
assignPositiveInteger(flatRuntime.session, 'registerTabId', state.grokRegisterTabId);
|
||||
assignCleanString(flatRuntime.session, 'pageState', state.grokPageState);
|
||||
assignCleanString(flatRuntime.session, 'pageUrl', state.grokPageUrl || state.grokPostVerificationUrl);
|
||||
assignCleanString(flatRuntime.register, 'email', state.grokEmail || state.email);
|
||||
assignCleanString(flatRuntime.register, 'firstName', state.grokFirstName);
|
||||
assignCleanString(flatRuntime.register, 'lastName', state.grokLastName);
|
||||
assignCleanString(flatRuntime.register, 'password', state.grokPassword);
|
||||
assignPositiveInteger(flatRuntime.register, 'verificationRequestedAt', state.grokVerificationRequestedAt);
|
||||
assignCleanString(flatRuntime.register, 'verificationCode', state.grokVerificationCode);
|
||||
assignCleanString(flatRuntime.register, 'status', state.grokRegisterStatus);
|
||||
assignPositiveInteger(flatRuntime.register, 'completedAt', state.grokCompletedAt);
|
||||
assignCleanString(flatRuntime.sso, 'currentCookie', state.grokSsoCookie);
|
||||
assignNonEmptyArray(flatRuntime.sso, 'cookies', state.grokSsoCookies);
|
||||
assignPositiveInteger(flatRuntime.sso, 'extractedAt', state.grokSsoExtractedAt || state.grokCompletedAt);
|
||||
assignCleanString(flatRuntime.upload, 'status', state.grokWebchat2ApiUploadStatus);
|
||||
assignPositiveInteger(flatRuntime.upload, 'uploadedAt', state.grokWebchat2ApiUploadedAt);
|
||||
assignCleanString(flatRuntime.upload, 'message', state.grokWebchat2ApiUploadMessage);
|
||||
assignCleanString(flatRuntime.upload, 'targetUrl', state.grokWebchat2ApiTargetUrl);
|
||||
return normalizeRuntimeState(deepMerge(deepMerge(runtimeFlowState.grok || {}, legacyFlowState), flatRuntime));
|
||||
}
|
||||
|
||||
@@ -346,6 +384,18 @@
|
||||
extractedAt: payload.grokSsoExtractedAt || payload.grokCompletedAt || 0,
|
||||
};
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(payload, 'grokWebchat2ApiUploadStatus')) {
|
||||
patch.upload = { ...(patch.upload || {}), status: payload.grokWebchat2ApiUploadStatus };
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(payload, 'grokWebchat2ApiUploadedAt')) {
|
||||
patch.upload = { ...(patch.upload || {}), uploadedAt: payload.grokWebchat2ApiUploadedAt };
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(payload, 'grokWebchat2ApiUploadMessage')) {
|
||||
patch.upload = { ...(patch.upload || {}), message: payload.grokWebchat2ApiUploadMessage };
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(payload, 'grokWebchat2ApiTargetUrl')) {
|
||||
patch.upload = { ...(patch.upload || {}), targetUrl: payload.grokWebchat2ApiTargetUrl };
|
||||
}
|
||||
if (!Object.keys(patch).length) {
|
||||
return {};
|
||||
}
|
||||
@@ -353,10 +403,7 @@
|
||||
}
|
||||
|
||||
function buildFreshKeepState(currentState = {}) {
|
||||
const currentRuntimeState = ensureRuntimeState(currentState);
|
||||
const nextRuntimeState = buildDefaultRuntimeState();
|
||||
nextRuntimeState.sso = currentRuntimeState.sso || buildDefaultRuntimeState().sso;
|
||||
return buildRuntimeStatePatch(currentState, nextRuntimeState);
|
||||
return buildRuntimeStatePatch(currentState, buildDefaultRuntimeState());
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
+20
-1
@@ -43,6 +43,10 @@
|
||||
groups: [
|
||||
'grok-target-webchat2api',
|
||||
],
|
||||
defaultState: {
|
||||
baseUrl: '',
|
||||
apiKey: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
publicationTargets: {},
|
||||
@@ -106,14 +110,26 @@
|
||||
'grok-extract-sso-cookie',
|
||||
],
|
||||
},
|
||||
'flows/grok/background/publisher-webchat2api': {
|
||||
sourceId: 'grok-webchat2api',
|
||||
commands: [
|
||||
'grok-upload-sso-to-webchat2api',
|
||||
],
|
||||
},
|
||||
},
|
||||
defaultTargetId: 'webchat2api',
|
||||
settingsDefaults: {
|
||||
targets: {
|
||||
webchat2api: {
|
||||
baseUrl: '',
|
||||
apiKey: '',
|
||||
},
|
||||
},
|
||||
autoRun: {
|
||||
stepExecutionRange: {
|
||||
enabled: false,
|
||||
fromStep: 1,
|
||||
toStep: 5,
|
||||
toStep: 6,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -122,6 +138,8 @@
|
||||
id: 'grok-target-webchat2api',
|
||||
label: 'webchat2api',
|
||||
rowIds: [
|
||||
'row-grok-webchat2api-url',
|
||||
'row-grok-webchat2api-key',
|
||||
'row-grok-sso-settings',
|
||||
],
|
||||
},
|
||||
@@ -131,6 +149,7 @@
|
||||
rowIds: [
|
||||
'row-grok-register-status',
|
||||
'row-grok-sso-status',
|
||||
'row-grok-webchat2api-upload-status',
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -64,6 +64,16 @@
|
||||
command: 'grok-extract-sso-cookie',
|
||||
flowId: 'grok',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
order: 60,
|
||||
key: 'grok-upload-sso-to-webchat2api',
|
||||
title: '上传 SSO 到 webchat2api',
|
||||
sourceId: 'grok-webchat2api',
|
||||
driverId: 'flows/grok/background/publisher-webchat2api',
|
||||
command: 'grok-upload-sso-to-webchat2api',
|
||||
flowId: 'grok',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user