feat(cursor): wire executor through portal, admin, and wechat routes

Register cursor in LLM executor bindings, route page/code tasks through
cursor runtime selection, and bootstrap wechat cursor policy services.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-08-27 09:33:47 +08:00
parent a29e1ec5c8
commit ad6dcc283f
17 changed files with 343 additions and 16 deletions
+26 -1
View File
@@ -320,7 +320,7 @@ test('listExecutorBindings returns all executor placeholders', async () => {
const bindings = await service.listExecutorBindings();
assert.deepEqual(
bindings.map((binding) => binding.executor),
['goose', 'aider', 'openhands'],
['goose', 'aider', 'openhands', 'cursor'],
);
assert.equal(bindings[0].enabled, false);
});
@@ -649,6 +649,31 @@ test('buildExecutorLaunchPlan rejects openhands headless without instruction', (
assert.match(plan.message ?? '', /instruction/);
});
test('buildExecutorLaunchPlan creates cursor headless command when enabled', () => {
const previous = process.env.MEMIND_CURSOR_EXECUTOR_ENABLED;
process.env.MEMIND_CURSOR_EXECUTOR_ENABLED = '1';
try {
const plan = buildExecutorLaunchPlan({
ok: true,
executor: 'cursor',
executorLabel: 'TKMind 智趣',
purpose: 'default',
env: {},
}, {
cwd: '/tmp/mindspace/user-1',
instruction: '生成 public/spring-poem.html',
});
assert.equal(plan.ok, true);
assert.equal(plan.executor, 'cursor');
assert.ok(plan.args.includes('--workspace'));
assert.ok(plan.args.includes('/tmp/mindspace/user-1'));
assert.match(plan.args.at(-1) ?? '', /spring-poem\.html/);
} finally {
if (previous === undefined) delete process.env.MEMIND_CURSOR_EXECUTOR_ENABLED;
else process.env.MEMIND_CURSOR_EXECUTOR_ENABLED = previous;
}
});
test('launchExecutor rejects goose launch path', async () => {
const pool = {
async query() {