feat: chat uploads, vision turn isolation, and MindSpace agent improvements
Add chat file/image upload UX, attachment proxying, vision thumbnails, and per-turn image scoping so agents only use the current upload. Extend MindSpace asset context, billing token state, OA/scenario verify scripts, and related runtime config. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -100,6 +100,35 @@ function createAdminLayoutPool(adminRow) {
|
||||
};
|
||||
}
|
||||
|
||||
function createRoleSkillSeedPool(adminRow, { existingRoleSkills = {} } = {}) {
|
||||
const roleSkills = { ...existingRoleSkills };
|
||||
const roleSkillSeedSql = [];
|
||||
const basePool = createAdminLayoutPool(adminRow);
|
||||
|
||||
return {
|
||||
roleSkills,
|
||||
roleSkillSeedSql,
|
||||
async query(sql, params = []) {
|
||||
if (
|
||||
sql.includes('INSERT INTO h5_user_skill_grants') &&
|
||||
sql.includes("VALUES ('role', 'user'")
|
||||
) {
|
||||
roleSkillSeedSql.push(sql);
|
||||
const [skillName, enabled] = params;
|
||||
if (skillName in roleSkills) {
|
||||
if (!sql.includes('ON DUPLICATE KEY UPDATE skill_name = skill_name')) {
|
||||
roleSkills[skillName] = enabled;
|
||||
}
|
||||
} else {
|
||||
roleSkills[skillName] = enabled;
|
||||
}
|
||||
return [[]];
|
||||
}
|
||||
return basePool.query(sql, params);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function createAgentPolicyPool(userRow) {
|
||||
return {
|
||||
async query(sql, params = []) {
|
||||
@@ -290,6 +319,38 @@ test('ensureAdminUser repairs existing admin workspace without password env', as
|
||||
assert.equal(adminRow.workspace_root, path.join(root, 'MindSpace', adminRow.id));
|
||||
});
|
||||
|
||||
test('ensureAdminUser seedRoleSkillDefaults preserves admin-configured role skill grants', async () => {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'memind-role-skill-seed-'));
|
||||
const adminRow = {
|
||||
id: 'admin-3',
|
||||
username: 'admin',
|
||||
slug: 'admin',
|
||||
email: 'admin@example.com',
|
||||
display_name: '管理员',
|
||||
role: 'admin',
|
||||
status: 'active',
|
||||
plan_type: 'free',
|
||||
workspace_root: path.join(root, 'MindSpace', 'admin-3'),
|
||||
balance_cents: 0,
|
||||
tokens_used: 0,
|
||||
};
|
||||
const pool = createRoleSkillSeedPool(adminRow, {
|
||||
existingRoleSkills: { 'static-page-publish': 1 },
|
||||
});
|
||||
const auth = createUserAuth(pool, {
|
||||
h5Root: root,
|
||||
env: { H5_PUBLIC_BASE_URL: 'https://example.com' },
|
||||
persistSessions: false,
|
||||
});
|
||||
|
||||
await auth.ensureAdminUser();
|
||||
|
||||
assert.equal(pool.roleSkills['static-page-publish'], 1);
|
||||
assert.ok(pool.roleSkillSeedSql.length > 0);
|
||||
assert.match(pool.roleSkillSeedSql[0], /ON DUPLICATE KEY UPDATE skill_name = skill_name/);
|
||||
assert.doesNotMatch(pool.roleSkillSeedSql.join('\n'), /ON DUPLICATE KEY UPDATE enabled = VALUES\(enabled\)/);
|
||||
});
|
||||
|
||||
test('agent session policy preserves sandbox root and exposes workspace ref metadata', async () => {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'memind-agent-policy-'));
|
||||
const userRow = {
|
||||
|
||||
Reference in New Issue
Block a user