164 lines
6.0 KiB
JavaScript
164 lines
6.0 KiB
JavaScript
import path from 'node:path';
|
||
import { DEFAULT_MAX_FILE_BYTES } from './mindspace.mjs';
|
||
import { createMindSpaceServiceFacade } from './mindspace-service.mjs';
|
||
import { createLocalMindSpaceStorageAdapter } from './mindspace-storage-adapter.mjs';
|
||
import { normalizeWorkspaceRelativePath } from './mindspace-workspace-relative-path.mjs';
|
||
import {
|
||
buildPublicUrl,
|
||
PUBLISH_ROOT_DIR,
|
||
resolveGoosedSandboxRoot,
|
||
resolvePublicBaseUrl,
|
||
resolvePublishDir,
|
||
} from './user-publish.mjs';
|
||
|
||
export function resolvePortalH5Root(codeRoot, env = process.env) {
|
||
const configuredRoot = String(env.MEMIND_PORTAL_H5_ROOT ?? '').trim();
|
||
return path.resolve(configuredRoot || codeRoot);
|
||
}
|
||
|
||
export function resolvePageWorkspaceRelativePath(row) {
|
||
const fromColumn = normalizeWorkspaceRelativePath(row?.workspace_relative_path);
|
||
if (fromColumn) return fromColumn;
|
||
let snapshot = row?.source_snapshot_json;
|
||
if (typeof snapshot === 'string') {
|
||
try {
|
||
snapshot = JSON.parse(snapshot);
|
||
} catch {
|
||
snapshot = null;
|
||
}
|
||
}
|
||
return normalizeWorkspaceRelativePath(snapshot?.relative_path);
|
||
}
|
||
|
||
export function isPublicWorkspaceHtmlRelativePath(relativePath) {
|
||
const normalized = normalizeWorkspaceRelativePath(relativePath);
|
||
return Boolean(normalized?.startsWith('public/') && normalized.toLowerCase().endsWith('.html'));
|
||
}
|
||
|
||
/** MindSpace 工作区静态页 canonical 公网 URL(/MindSpace/<用户ID>/public/...) */
|
||
export function resolveWorkspaceMindSpacePublicUrl({
|
||
h5Root,
|
||
env = process.env,
|
||
userId,
|
||
relativePath,
|
||
} = {}) {
|
||
const normalized = normalizeWorkspaceRelativePath(relativePath);
|
||
if (!userId || !normalized || !isPublicWorkspaceHtmlRelativePath(normalized)) return null;
|
||
return buildMindSpacePublicUrlForUser({
|
||
h5Root: h5Root ?? process.cwd(),
|
||
env,
|
||
user: userId,
|
||
relativePath: normalized,
|
||
});
|
||
}
|
||
|
||
export function resolveMindSpaceStorageRoot(h5Root, env = process.env) {
|
||
return path.resolve(env.MINDSPACE_STORAGE_ROOT ?? path.join(h5Root, 'data', 'mindspace'));
|
||
}
|
||
|
||
export function resolveMindSpaceRuntimeConfig(h5Root, env = process.env) {
|
||
return {
|
||
storageRoot: resolveMindSpaceStorageRoot(h5Root, env),
|
||
publicBaseUrl: resolvePublicBaseUrl(env),
|
||
};
|
||
}
|
||
|
||
export function resolveMindSpaceServerRuntimeOptions(h5Root, env = process.env) {
|
||
const runtime = resolveMindSpaceRuntimeConfig(h5Root, env);
|
||
return {
|
||
...runtime,
|
||
adapterKind: String(env.MINDSPACE_SERVER_ADAPTER ?? 'local').trim().toLowerCase() || 'local',
|
||
publishRoot: resolveMindSpacePublishRoot(h5Root),
|
||
maxFileBytes: Number(env.MINDSPACE_MAX_FILE_BYTES ?? DEFAULT_MAX_FILE_BYTES),
|
||
aiDailyLimit: Number(env.MINDSPACE_FREE_AI_DAILY_LIMIT ?? 10),
|
||
publicPageLimit: Number(env.MINDSPACE_FREE_PUBLIC_PAGE_LIMIT ?? 5),
|
||
monthlyViewLimit: Number(env.MINDSPACE_FREE_MONTHLY_VIEW_LIMIT ?? 1000),
|
||
experienceEnabled: env.MINDSPACE_EXPERIENCE_ENABLED !== 'false',
|
||
agentWorker: {
|
||
enabled: env.MINDSPACE_AGENT_WORKER_ENABLED === 'true',
|
||
concurrency: Math.max(1, Number(env.MINDSPACE_AGENT_WORKER_CONCURRENCY ?? 2)),
|
||
pollMs: Math.max(200, Number(env.MINDSPACE_AGENT_WORKER_POLL_MS ?? 1000)),
|
||
staleMs: Math.max(10_000, Number(env.MINDSPACE_AGENT_WORKER_STALE_MS ?? 5 * 60 * 1000)),
|
||
ssePollMs: Math.max(500, Number(env.MINDSPACE_AGENT_SSE_POLL_MS ?? 1000)),
|
||
},
|
||
remote: {
|
||
baseUrl: String(env.MINDSPACE_REMOTE_BASE_URL ?? '').trim(),
|
||
authToken: String(env.MINDSPACE_REMOTE_AUTH_TOKEN ?? '').trim(),
|
||
operationBasePath: String(env.MINDSPACE_REMOTE_OPERATION_BASE_PATH ?? '/mindspace/v1/adapter')
|
||
.trim(),
|
||
timeoutMs: Math.max(1000, Number(env.MINDSPACE_REMOTE_TIMEOUT_MS ?? 15_000)),
|
||
},
|
||
};
|
||
}
|
||
|
||
export function resolveMindSpacePublishRoot(h5Root) {
|
||
return path.resolve(h5Root, PUBLISH_ROOT_DIR);
|
||
}
|
||
|
||
export function resolveMindSpaceUserPublishDir(h5Root, user) {
|
||
return path.resolve(resolvePublishDir(h5Root, user));
|
||
}
|
||
|
||
export function buildMindSpacePublicRoutePath(ownerKey, segments = []) {
|
||
const userId = String(ownerKey ?? '').trim();
|
||
if (!userId) {
|
||
throw new Error('MindSpace public route requires an owner key');
|
||
}
|
||
const cleanSegments = Array.isArray(segments)
|
||
? segments.map((segment) => encodeURIComponent(String(segment ?? '')))
|
||
: [];
|
||
return `/${PUBLISH_ROOT_DIR}/${encodeURIComponent(userId)}${cleanSegments.length ? `/${cleanSegments.join('/')}` : '/'}`;
|
||
}
|
||
|
||
export function buildMindSpacePublicUrlForUser({ h5Root, env = process.env, user, relativePath = '' } = {}) {
|
||
const ownerKey =
|
||
typeof user === 'string' || typeof user === 'number'
|
||
? String(user)
|
||
: String(user?.id ?? '').trim();
|
||
if (!ownerKey) {
|
||
throw new Error('MindSpace public URL requires a user id');
|
||
}
|
||
const { publicBaseUrl } = resolveMindSpaceRuntimeConfig(h5Root, env);
|
||
return buildPublicUrl(publicBaseUrl, ownerKey, relativePath);
|
||
}
|
||
|
||
export function buildMindSpaceWorkspaceRef(user) {
|
||
const ownerKey =
|
||
typeof user === 'string' || typeof user === 'number'
|
||
? String(user)
|
||
: String(user?.id ?? '').trim();
|
||
if (!ownerKey) {
|
||
throw new Error('MindSpace workspace ref requires a user id');
|
||
}
|
||
return `mindspace://users/${encodeURIComponent(ownerKey)}/workspace`;
|
||
}
|
||
|
||
export function resolveMindSpaceAgentWorkspaceCapability({ h5Root, env = process.env, user } = {}) {
|
||
return {
|
||
workspaceRoot: resolveMindSpaceUserPublishDir(h5Root, user),
|
||
sandboxRoot: resolveGoosedSandboxRoot(h5Root, user, env),
|
||
workspaceRef: buildMindSpaceWorkspaceRef(user),
|
||
};
|
||
}
|
||
|
||
export function createMindSpaceLocalRuntime({
|
||
h5Root,
|
||
env = process.env,
|
||
conversationPackageBackfill,
|
||
conversationPackagePublicHtmlHydrator,
|
||
logger = console,
|
||
} = {}) {
|
||
const config = resolveMindSpaceRuntimeConfig(h5Root, env);
|
||
return {
|
||
...config,
|
||
storageAdapter: createLocalMindSpaceStorageAdapter(config.storageRoot),
|
||
serviceFacade: createMindSpaceServiceFacade({
|
||
storageAdapter: createLocalMindSpaceStorageAdapter(config.storageRoot),
|
||
publicBaseUrl: config.publicBaseUrl,
|
||
conversationPackageBackfill,
|
||
conversationPackagePublicHtmlHydrator,
|
||
logger,
|
||
}),
|
||
};
|
||
}
|