239 lines
7.0 KiB
JavaScript
239 lines
7.0 KiB
JavaScript
import { createAssetGatewayConfigService } from '../asset-gateway.mjs';
|
|
import { createExperienceService } from '../experience-service.mjs';
|
|
import { createImageMakeAdminConfigService } from '../image-make-admin-config.mjs';
|
|
import { createImageMakeClientFromEnv } from '../image-make-client.mjs';
|
|
import { createLlmProviderService, RELAY_BOOTSTRAP } from '../llm-providers.mjs';
|
|
import { createMindSpaceAgentRunner } from '../mindspace-agent-runner.mjs';
|
|
import { createMindSpaceAuditWriter } from '../mindspace-audit.mjs';
|
|
import { createMindSpaceImageGenerationService } from '../mindspace-image-generation.mjs';
|
|
import { createMindSpaceImageReviewService } from '../mindspace-image-review.mjs';
|
|
import { createWordFilterService } from '../word-filter.mjs';
|
|
import { isPassiveCanaryRuntime } from './portal-runtime-role.mjs';
|
|
|
|
async function createPgExperienceServiceFromModule(options) {
|
|
const { createPgExperienceService } = await import(
|
|
'../experience-service-pg.mjs'
|
|
);
|
|
return createPgExperienceService(options);
|
|
}
|
|
|
|
export async function bootstrapPortalAgentServices({
|
|
pool,
|
|
env = process.env,
|
|
runtime,
|
|
apiTarget,
|
|
apiTargets,
|
|
apiSecret,
|
|
userAuth,
|
|
sessionAccess,
|
|
mindSpaceRuntimeAdapter,
|
|
mindSpaceAssets,
|
|
resolveUserIdByDirKey,
|
|
workspaceMaintenanceEnabled = true,
|
|
startWorkspaceThumbnailWatcher,
|
|
startWorkspaceAssetSyncWatcher,
|
|
logger = console,
|
|
createExperienceServiceFn = createExperienceService,
|
|
createPgExperienceServiceFn =
|
|
createPgExperienceServiceFromModule,
|
|
createMindSpaceAgentRunnerFn =
|
|
createMindSpaceAgentRunner,
|
|
createMindSpaceAuditWriterFn =
|
|
createMindSpaceAuditWriter,
|
|
createLlmProviderServiceFn = createLlmProviderService,
|
|
createAssetGatewayConfigServiceFn =
|
|
createAssetGatewayConfigService,
|
|
createImageMakeAdminConfigServiceFn =
|
|
createImageMakeAdminConfigService,
|
|
createImageMakeClientFromEnvFn =
|
|
createImageMakeClientFromEnv,
|
|
createMindSpaceImageReviewServiceFn =
|
|
createMindSpaceImageReviewService,
|
|
createMindSpaceImageGenerationServiceFn =
|
|
createMindSpaceImageGenerationService,
|
|
createWordFilterServiceFn = createWordFilterService,
|
|
relayBootstrap = RELAY_BOOTSTRAP,
|
|
} = {}) {
|
|
if (
|
|
!pool ||
|
|
!runtime ||
|
|
!userAuth ||
|
|
!sessionAccess ||
|
|
!mindSpaceRuntimeAdapter?.agentJobService ||
|
|
typeof mindSpaceRuntimeAdapter.startBackgroundJobs !==
|
|
'function' ||
|
|
!mindSpaceAssets ||
|
|
typeof resolveUserIdByDirKey !== 'function' ||
|
|
typeof startWorkspaceThumbnailWatcher !== 'function' ||
|
|
typeof startWorkspaceAssetSyncWatcher !== 'function'
|
|
) {
|
|
throw new Error(
|
|
'bootstrapPortalAgentServices requires runtime service dependencies',
|
|
);
|
|
}
|
|
|
|
const mindSpaceAgentJobs =
|
|
mindSpaceRuntimeAdapter.agentJobService;
|
|
let experienceService = null;
|
|
if (runtime.experienceEnabled) {
|
|
if (env.EXPERIENCE_PG_URL) {
|
|
try {
|
|
experienceService =
|
|
await createPgExperienceServiceFn({
|
|
connectionString: env.EXPERIENCE_PG_URL,
|
|
});
|
|
logger.log(
|
|
'Experience store: PostgreSQL + pgvector',
|
|
);
|
|
} catch (error) {
|
|
logger.error(
|
|
'Experience PG init failed, falling back to MySQL store:',
|
|
error instanceof Error ? error.message : error,
|
|
);
|
|
experienceService = createExperienceServiceFn(pool);
|
|
}
|
|
} else {
|
|
experienceService = createExperienceServiceFn(pool);
|
|
}
|
|
}
|
|
|
|
const mindSpaceAgentRunner =
|
|
createMindSpaceAgentRunnerFn({
|
|
apiTarget,
|
|
apiSecret,
|
|
userAuth,
|
|
sessionAccess,
|
|
agentJobService: mindSpaceAgentJobs,
|
|
experienceService,
|
|
});
|
|
const mindSpaceAudit =
|
|
createMindSpaceAuditWriterFn(pool);
|
|
|
|
if (isPassiveCanaryRuntime(env)) {
|
|
logger.log('Passive candidate runtime: MindSpace background jobs disabled');
|
|
} else {
|
|
mindSpaceRuntimeAdapter.startBackgroundJobs({
|
|
publicationCleanupIntervalMs: 60 * 1000,
|
|
agentWorker: runtime.agentWorker,
|
|
agentRunner: mindSpaceAgentRunner,
|
|
workspaceMaintenanceEnabled,
|
|
publishRoot: runtime.publishRoot,
|
|
startWorkspaceThumbnailWatcher,
|
|
startWorkspaceAssetSyncWatcher,
|
|
syncUserWorkspaceByDirKey: async (
|
|
dirKey,
|
|
options,
|
|
) => {
|
|
const userId =
|
|
await resolveUserIdByDirKey(dirKey);
|
|
if (!userId) return;
|
|
await mindSpaceAssets.syncWorkspaceAssets(
|
|
userId,
|
|
options,
|
|
);
|
|
},
|
|
expireStaleUploadsIntervalMs: 5 * 60 * 1000,
|
|
});
|
|
}
|
|
|
|
await userAuth.ensureAdminUser();
|
|
const userDataSpaceBackfill =
|
|
await userAuth.ensureAllUserDataSpaces();
|
|
if (userDataSpaceBackfill.errors.length > 0) {
|
|
logger.warn(
|
|
`[PageData] PG space backfill incomplete: ${userDataSpaceBackfill.errors.length} user(s) failed`,
|
|
);
|
|
}
|
|
|
|
const llmProviderService =
|
|
createLlmProviderServiceFn(pool, {
|
|
apiTarget,
|
|
apiTargets,
|
|
apiSecret,
|
|
});
|
|
const assetGatewayConfigService =
|
|
createAssetGatewayConfigServiceFn(pool, {
|
|
llmProviderService,
|
|
});
|
|
const imageMakeAdminConfigService =
|
|
createImageMakeAdminConfigServiceFn(pool, {
|
|
env,
|
|
llmProviderService,
|
|
});
|
|
await imageMakeAdminConfigService.ensureSchema();
|
|
|
|
let imageMakeClient = null;
|
|
try {
|
|
imageMakeClient =
|
|
createImageMakeClientFromEnvFn(env);
|
|
} catch (error) {
|
|
logger.warn(
|
|
'[image_make] invalid local configuration; integration stays disabled:',
|
|
error?.message ?? error,
|
|
);
|
|
}
|
|
const imageReviewService =
|
|
createMindSpaceImageReviewServiceFn({
|
|
llmProviderService,
|
|
env,
|
|
logger,
|
|
});
|
|
const mindSpaceImageGeneration =
|
|
createMindSpaceImageGenerationServiceFn({
|
|
configService: assetGatewayConfigService,
|
|
assetService: mindSpaceAssets,
|
|
imageMakeClient,
|
|
imageReviewService,
|
|
env,
|
|
logger,
|
|
});
|
|
const wordFilterService =
|
|
createWordFilterServiceFn(pool);
|
|
|
|
const relayBootstrapTask = env.H5_RELAY_BOOTSTRAP_DISABLED === '1'
|
|
? Promise.resolve({ ok: true, created: false, skipped: true })
|
|
: llmProviderService
|
|
.ensureBootstrapRelay()
|
|
.then((result) => {
|
|
if (result.created) {
|
|
logger.log(
|
|
`LLM relay bootstrap created: ${relayBootstrap.name}`,
|
|
);
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
logger.warn(
|
|
'LLM relay bootstrap skipped:',
|
|
error instanceof Error ? error.message : error,
|
|
);
|
|
});
|
|
void relayBootstrapTask;
|
|
|
|
const providerSyncTask = llmProviderService
|
|
.syncSelectedToGoosed()
|
|
.catch((error) => {
|
|
logger.warn(
|
|
'LLM provider boot sync skipped:',
|
|
error instanceof Error ? error.message : error,
|
|
);
|
|
});
|
|
void providerSyncTask;
|
|
|
|
return {
|
|
mindSpaceAgentJobs,
|
|
experienceService,
|
|
mindSpaceAgentRunner,
|
|
mindSpaceAudit,
|
|
userDataSpaceBackfill,
|
|
llmProviderService,
|
|
assetGatewayConfigService,
|
|
imageMakeAdminConfigService,
|
|
imageMakeClient,
|
|
imageReviewService,
|
|
mindSpaceImageGeneration,
|
|
wordFilterService,
|
|
relayBootstrapTask,
|
|
providerSyncTask,
|
|
};
|
|
}
|