Expose conversation package manifests
This commit is contained in:
@@ -14,6 +14,7 @@ export function createConversationPackageRegistry({ store, service } = {}) {
|
|||||||
requireMethod(store, 'getPackageBySession', 'missing_conversation_package_store');
|
requireMethod(store, 'getPackageBySession', 'missing_conversation_package_store');
|
||||||
requireMethod(store, 'listArtifacts', 'missing_conversation_package_store');
|
requireMethod(store, 'listArtifacts', 'missing_conversation_package_store');
|
||||||
requireMethod(service, 'putConversationManifest', 'missing_mindspace_service');
|
requireMethod(service, 'putConversationManifest', 'missing_mindspace_service');
|
||||||
|
requireMethod(service, 'buildConversationManifest', 'missing_mindspace_service');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
async ensurePackage(input) {
|
async ensurePackage(input) {
|
||||||
@@ -30,6 +31,13 @@ export function createConversationPackageRegistry({ store, service } = {}) {
|
|||||||
const artifacts = await store.listArtifacts(packageRecord.id);
|
const artifacts = await store.listArtifacts(packageRecord.id);
|
||||||
return service.putConversationManifest({ packageRecord, artifacts });
|
return service.putConversationManifest({ packageRecord, artifacts });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async readManifestForSession({ userId, sessionId }) {
|
||||||
|
const packageRecord = await store.getPackageBySession(userId, sessionId);
|
||||||
|
if (!packageRecord) return null;
|
||||||
|
const artifacts = await store.listArtifacts(packageRecord.id);
|
||||||
|
return service.buildConversationManifest({ packageRecord, artifacts });
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -150,6 +150,46 @@ test('conversation package registry records artifacts and writes manifest throug
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('conversation package registry reads manifest without writing storage', async () => {
|
||||||
|
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'mindspace-registry-'));
|
||||||
|
const service = createMindSpaceServiceFacade({
|
||||||
|
storageAdapter: createLocalMindSpaceStorageAdapter(root),
|
||||||
|
publicBaseUrl: 'https://m.tkmind.cn',
|
||||||
|
});
|
||||||
|
const store = createConversationPackageStore(createFakePool());
|
||||||
|
const registry = createConversationPackageRegistry({ store, service });
|
||||||
|
const packageRecord = await registry.ensurePackage({
|
||||||
|
userId: 'user-1',
|
||||||
|
sessionId: 'session-1',
|
||||||
|
title: '输入与页面',
|
||||||
|
now: 1000,
|
||||||
|
});
|
||||||
|
await registry.recordArtifact({
|
||||||
|
id: 'ca_image',
|
||||||
|
packageId: packageRecord.id,
|
||||||
|
artifactKind: 'input_image',
|
||||||
|
displayName: 'cover.png',
|
||||||
|
sortOrder: 1,
|
||||||
|
now: 1000,
|
||||||
|
});
|
||||||
|
|
||||||
|
const manifest = await registry.readManifestForSession({
|
||||||
|
userId: 'user-1',
|
||||||
|
sessionId: 'session-1',
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(manifest.packageId, 'cp_session-1');
|
||||||
|
assert.equal(manifest.title, '输入与页面');
|
||||||
|
assert.deepEqual(
|
||||||
|
manifest.artifacts.map((item) => item.kind),
|
||||||
|
['input_image'],
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
await service.statPackageObject({ packageRecord, relativePath: 'manifest.json' }).then((stat) => stat.exists),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('conversation package registry skips manifest writes for unknown sessions', async () => {
|
test('conversation package registry skips manifest writes for unknown sessions', async () => {
|
||||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'mindspace-registry-'));
|
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'mindspace-registry-'));
|
||||||
const registry = createConversationPackageRegistry({
|
const registry = createConversationPackageRegistry({
|
||||||
|
|||||||
+27
-4
@@ -253,6 +253,7 @@ let conversationMemoryService = null;
|
|||||||
let mindSpace = null;
|
let mindSpace = null;
|
||||||
let mindSpaceAssets = null;
|
let mindSpaceAssets = null;
|
||||||
let mindSpaceAudit = null;
|
let mindSpaceAudit = null;
|
||||||
|
let mindSpaceConversationPackageRegistry = null;
|
||||||
let mindSpacePages = null;
|
let mindSpacePages = null;
|
||||||
let mindSpacePageLiveEdit = null;
|
let mindSpacePageLiveEdit = null;
|
||||||
let mindSpaceAssetAgent = null;
|
let mindSpaceAssetAgent = null;
|
||||||
@@ -303,7 +304,7 @@ async function bootstrapUserAuth() {
|
|||||||
});
|
});
|
||||||
const mindSpaceStorageRoot =
|
const mindSpaceStorageRoot =
|
||||||
process.env.MINDSPACE_STORAGE_ROOT ?? path.join(__dirname, 'data', 'mindspace');
|
process.env.MINDSPACE_STORAGE_ROOT ?? path.join(__dirname, 'data', 'mindspace');
|
||||||
const conversationPackageRegistry = createConversationPackageRegistry({
|
mindSpaceConversationPackageRegistry = createConversationPackageRegistry({
|
||||||
store: createConversationPackageStore(pool),
|
store: createConversationPackageStore(pool),
|
||||||
service: createMindSpaceServiceFacade({
|
service: createMindSpaceServiceFacade({
|
||||||
storageAdapter: createLocalMindSpaceStorageAdapter(mindSpaceStorageRoot),
|
storageAdapter: createLocalMindSpaceStorageAdapter(mindSpaceStorageRoot),
|
||||||
@@ -314,12 +315,12 @@ async function bootstrapUserAuth() {
|
|||||||
h5Root: __dirname,
|
h5Root: __dirname,
|
||||||
storageRoot: mindSpaceStorageRoot,
|
storageRoot: mindSpaceStorageRoot,
|
||||||
maxFileBytes: Number(process.env.MINDSPACE_MAX_FILE_BYTES ?? DEFAULT_MAX_FILE_BYTES),
|
maxFileBytes: Number(process.env.MINDSPACE_MAX_FILE_BYTES ?? DEFAULT_MAX_FILE_BYTES),
|
||||||
conversationPackageRegistry,
|
conversationPackageRegistry: mindSpaceConversationPackageRegistry,
|
||||||
});
|
});
|
||||||
mindSpacePages = createPageService(pool, {
|
mindSpacePages = createPageService(pool, {
|
||||||
h5Root: __dirname,
|
h5Root: __dirname,
|
||||||
storageRoot: mindSpaceStorageRoot,
|
storageRoot: mindSpaceStorageRoot,
|
||||||
conversationPackageRegistry,
|
conversationPackageRegistry: mindSpaceConversationPackageRegistry,
|
||||||
});
|
});
|
||||||
const resolveUserIdForAgentSession = async (sessionId) => {
|
const resolveUserIdForAgentSession = async (sessionId) => {
|
||||||
const [rows] = await pool.query(
|
const [rows] = await pool.query(
|
||||||
@@ -340,7 +341,7 @@ async function bootstrapUserAuth() {
|
|||||||
h5Root: __dirname,
|
h5Root: __dirname,
|
||||||
storageRoot: mindSpaceStorageRoot,
|
storageRoot: mindSpaceStorageRoot,
|
||||||
publicPageLimit: Number(process.env.MINDSPACE_FREE_PUBLIC_PAGE_LIMIT ?? 5),
|
publicPageLimit: Number(process.env.MINDSPACE_FREE_PUBLIC_PAGE_LIMIT ?? 5),
|
||||||
conversationPackageRegistry,
|
conversationPackageRegistry: mindSpaceConversationPackageRegistry,
|
||||||
});
|
});
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
@@ -2486,6 +2487,28 @@ api.post('/internal/agent/jobs/:jobId/complete', async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
api.get('/mindspace/v1/conversation-packages/:sessionId', async (req, res) => {
|
||||||
|
if (!mindSpaceConversationPackageRegistry || !ensureMindSpaceEnabled(res, req)) {
|
||||||
|
if (res.headersSent) return;
|
||||||
|
return res.status(503).json({ message: 'MindSpace 对话包未启用' });
|
||||||
|
}
|
||||||
|
const sessionId = String(req.params.sessionId ?? '').trim();
|
||||||
|
if (!sessionId) return res.status(400).json({ message: '缺少 sessionId' });
|
||||||
|
if (!(await userAuth.ownsSession(req.currentUser.id, sessionId))) {
|
||||||
|
return res.status(403).json({ message: '无权访问该会话' });
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const manifest = await mindSpaceConversationPackageRegistry.readManifestForSession({
|
||||||
|
userId: req.currentUser.id,
|
||||||
|
sessionId,
|
||||||
|
});
|
||||||
|
if (!manifest) return res.status(404).json({ message: '对话包不存在' });
|
||||||
|
return sendData(res, req, manifest);
|
||||||
|
} catch (error) {
|
||||||
|
return mindSpaceError(res, req, error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
api.post('/mindspace/v1/uploads', async (req, res) => {
|
api.post('/mindspace/v1/uploads', async (req, res) => {
|
||||||
if (!mindSpaceAssets || !ensureMindSpaceEnabled(res, req, { upload: true })) return;
|
if (!mindSpaceAssets || !ensureMindSpaceEnabled(res, req, { upload: true })) return;
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user