303 lines
8.1 KiB
JavaScript
303 lines
8.1 KiB
JavaScript
import {
|
|
resolveAnalyticsOwnerLabel,
|
|
resolveAnalyticsOwnerSegment,
|
|
resolveAnalyticsPlan,
|
|
sendMindSpaceAnalyticsEvent,
|
|
} from '../mindspace-analytics.mjs';
|
|
import {
|
|
sendMindSpaceRybbitEvent,
|
|
} from '../mindspace-rybbit.mjs';
|
|
import { createPageEditSessionService } from '../mindspace-page-edit-session.mjs';
|
|
import { createNotificationDispatcher } from '../notification-dispatcher.mjs';
|
|
import { startScheduleReminderWorker } from '../schedule-reminder-worker.mjs';
|
|
import { isPassiveCanaryRuntime } from './portal-runtime-role.mjs';
|
|
import { loadWechatMpModule } from '../wechat-mp-loader.mjs';
|
|
|
|
export async function bootstrapPortalIntegrationServices({
|
|
pool,
|
|
h5Root,
|
|
env = process.env,
|
|
usersRoot,
|
|
wechatMpConfig,
|
|
mindSpacePublicFinish,
|
|
userAuth,
|
|
sessionAccess,
|
|
tkmindProxy,
|
|
scheduleService,
|
|
wechatScheduleLlmConfigService,
|
|
llmProviderService,
|
|
chatIntentRouter,
|
|
systemDisclosurePolicyService,
|
|
sessionSnapshotService,
|
|
mindSpaceAnalyticsConfig,
|
|
mindSpaceRybbitConfig,
|
|
subscriptionService,
|
|
apiTarget,
|
|
apiSecret,
|
|
mindSpacePages,
|
|
mindSpacePageLiveEdit,
|
|
logger = console,
|
|
loadWechatMpModuleFn = loadWechatMpModule,
|
|
resolveAnalyticsOwnerSegmentFn =
|
|
resolveAnalyticsOwnerSegment,
|
|
resolveAnalyticsOwnerLabelFn =
|
|
resolveAnalyticsOwnerLabel,
|
|
resolveAnalyticsPlanFn = resolveAnalyticsPlan,
|
|
sendMindSpaceAnalyticsEventFn =
|
|
sendMindSpaceAnalyticsEvent,
|
|
sendMindSpaceRybbitEventFn =
|
|
sendMindSpaceRybbitEvent,
|
|
createNotificationDispatcherFn =
|
|
createNotificationDispatcher,
|
|
startScheduleReminderWorkerFn =
|
|
startScheduleReminderWorker,
|
|
createPageEditSessionServiceFn =
|
|
createPageEditSessionService,
|
|
setIntervalFn = setInterval,
|
|
} = {}) {
|
|
if (
|
|
!pool ||
|
|
!h5Root ||
|
|
!usersRoot ||
|
|
!userAuth ||
|
|
!sessionAccess ||
|
|
!tkmindProxy ||
|
|
!llmProviderService
|
|
) {
|
|
throw new Error(
|
|
'bootstrapPortalIntegrationServices requires Portal integration dependencies',
|
|
);
|
|
}
|
|
|
|
const wechatMp = await loadWechatMpModuleFn(h5Root);
|
|
const wechatMpService =
|
|
wechatMp.createWechatMpService({
|
|
config: wechatMpConfig,
|
|
userAuth,
|
|
sessionAccess,
|
|
htmlDeliveryAuthority:
|
|
typeof mindSpacePublicFinish
|
|
?.prepareWechatHtmlDelivery ===
|
|
'function' &&
|
|
typeof mindSpacePublicFinish
|
|
?.ensureWechatFreshPageThumbnails ===
|
|
'function'
|
|
? mindSpacePublicFinish
|
|
: null,
|
|
pageDataFinishGuard:
|
|
typeof mindSpacePublicFinish
|
|
?.prepareWechatPageDataDelivery ===
|
|
'function'
|
|
? mindSpacePublicFinish
|
|
: null,
|
|
apiFetch: tkmindProxy.apiFetch,
|
|
startAgentSession: ({
|
|
userId,
|
|
workingDir,
|
|
sessionPolicy,
|
|
}) =>
|
|
tkmindProxy.startSessionForUser(userId, {
|
|
workingDir,
|
|
sessionPolicy,
|
|
}),
|
|
sessionApiFetch: async (
|
|
sessionId,
|
|
pathname,
|
|
init,
|
|
) => {
|
|
const target =
|
|
await tkmindProxy.resolveTarget(sessionId);
|
|
return tkmindProxy.apiFetchTo(
|
|
target,
|
|
pathname,
|
|
init,
|
|
);
|
|
},
|
|
submitSessionReply: ({
|
|
userId,
|
|
sessionId,
|
|
requestId,
|
|
userMessage,
|
|
options,
|
|
}) =>
|
|
tkmindProxy.submitSessionReplyForUser(
|
|
userId,
|
|
sessionId,
|
|
requestId,
|
|
userMessage,
|
|
options,
|
|
),
|
|
scheduleService:
|
|
env.H5_SCHEDULE_ENABLED === '1'
|
|
? scheduleService
|
|
: null,
|
|
wechatScheduleLlmConfigService,
|
|
llmProviderService,
|
|
chatIntentRouter,
|
|
systemDisclosurePolicyService,
|
|
sessionIntentClassifier: ({ text }) =>
|
|
chatIntentRouter?.classifySessionAction({
|
|
text,
|
|
}),
|
|
onPageGenerated: async ({
|
|
userId,
|
|
sessionId,
|
|
artifacts = [],
|
|
}) => {
|
|
for (const artifact of artifacts) {
|
|
const pageOwner =
|
|
(await userAuth
|
|
?.getUserById(userId)
|
|
.catch(() => null)) ?? {};
|
|
const analyticsPayload = {
|
|
eventName: 'page_generated',
|
|
ownerId: userId,
|
|
ownerSegment:
|
|
resolveAnalyticsOwnerSegmentFn(
|
|
pageOwner,
|
|
),
|
|
ownerLabel: resolveAnalyticsOwnerLabelFn(
|
|
pageOwner,
|
|
),
|
|
planType: resolveAnalyticsPlanFn(pageOwner),
|
|
generatedAt: new Date().toISOString(),
|
|
pageId: artifact.relativePath,
|
|
publicationId: sessionId,
|
|
agentRunId: sessionId,
|
|
channel: 'wechat_mp',
|
|
url:
|
|
artifact.url ||
|
|
artifact.relativePath ||
|
|
'/',
|
|
};
|
|
void sendMindSpaceAnalyticsEventFn({
|
|
config: mindSpaceAnalyticsConfig,
|
|
...analyticsPayload,
|
|
});
|
|
void sendMindSpaceRybbitEventFn({
|
|
config: mindSpaceRybbitConfig,
|
|
...analyticsPayload,
|
|
});
|
|
}
|
|
},
|
|
applySessionLlmProvider: (sessionId) =>
|
|
tkmindProxy.applySessionLlmProvider(sessionId),
|
|
refreshSessionSnapshot:
|
|
sessionSnapshotService?.isEnabled()
|
|
? (sessionId, userId) =>
|
|
sessionSnapshotService.refresh(
|
|
sessionId,
|
|
userId,
|
|
async (pathname, init) => {
|
|
const target =
|
|
await tkmindProxy.resolveTarget(
|
|
sessionId,
|
|
);
|
|
return tkmindProxy.apiFetchTo(
|
|
target,
|
|
pathname,
|
|
init,
|
|
);
|
|
},
|
|
)
|
|
: null,
|
|
});
|
|
|
|
const notificationDispatcher =
|
|
createNotificationDispatcherFn({
|
|
sendWechatTextToUser: wechatMpService?.enabled
|
|
? (userId, text) =>
|
|
wechatMpService.sendTextToUser(
|
|
userId,
|
|
text,
|
|
)
|
|
: null,
|
|
});
|
|
userAuth.setRechargeNotifier(
|
|
async ({ userId, title, body, dedupeKey }) => {
|
|
await notificationDispatcher.sendRechargeSuccess({
|
|
userId,
|
|
title,
|
|
body,
|
|
dedupeKey,
|
|
});
|
|
},
|
|
);
|
|
|
|
let scheduleReminderWorker = null;
|
|
if (
|
|
!isPassiveCanaryRuntime(env) &&
|
|
env.H5_REMINDER_WORKER_ENABLED === '1' &&
|
|
wechatMpService?.enabled &&
|
|
scheduleService
|
|
) {
|
|
scheduleReminderWorker =
|
|
startScheduleReminderWorkerFn({
|
|
scheduleService,
|
|
notificationDispatcher,
|
|
});
|
|
logger.log('Schedule reminder worker enabled');
|
|
}
|
|
|
|
let subscriptionExpiryTimer = null;
|
|
if (subscriptionService && !isPassiveCanaryRuntime(env)) {
|
|
subscriptionExpiryTimer = setIntervalFn(
|
|
async () => {
|
|
try {
|
|
const { renewed, failed } =
|
|
await subscriptionService.processAutoRenewals();
|
|
if (renewed > 0) {
|
|
logger.log(
|
|
`Auto-renewed ${renewed} subscription(s)`,
|
|
);
|
|
}
|
|
if (failed > 0) {
|
|
logger.log(
|
|
`Auto-renew failed for ${failed} subscription(s) (balance insufficient)`,
|
|
);
|
|
}
|
|
const expired =
|
|
await subscriptionService.expireStaleSubscriptions();
|
|
if (expired > 0) {
|
|
logger.log(
|
|
`Expired ${expired} stale subscription(s)`,
|
|
);
|
|
}
|
|
} catch (error) {
|
|
logger.warn(
|
|
'Subscription expiry check failed:',
|
|
error,
|
|
);
|
|
}
|
|
},
|
|
60 * 60 * 1000,
|
|
);
|
|
subscriptionExpiryTimer.unref?.();
|
|
}
|
|
|
|
const mindSpacePageEditSession =
|
|
createPageEditSessionServiceFn({
|
|
apiTarget,
|
|
apiSecret,
|
|
userAuth,
|
|
sessionAccess,
|
|
pageService: mindSpacePages,
|
|
pageLiveEdit: mindSpacePageLiveEdit,
|
|
llmProviderService,
|
|
});
|
|
if (wechatMpService?.enabled) {
|
|
logger.log('WeChat MP webhook enabled');
|
|
}
|
|
logger.log(
|
|
`User auth enabled (MySQL), workspace root: ${usersRoot}`,
|
|
);
|
|
|
|
return {
|
|
wechatMpService,
|
|
notificationDispatcher,
|
|
scheduleReminderWorker,
|
|
subscriptionExpiryTimer,
|
|
mindSpacePageEditSession,
|
|
};
|
|
}
|