feat(agents): conversations.findOrCreateGlobal for space-less agents

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
root
2026-06-04 21:04:31 +10:00
parent 92299548ee
commit e8dfc8f392
2 changed files with 35 additions and 0 deletions

View File

@@ -43,6 +43,22 @@ export async function setSummary(id, summary) {
return r;
}
export async function findOrCreateGlobal(agent_id, actor) {
const { rows: [existing] } = await pool.query(
`SELECT * FROM conversations
WHERE agent_id=$1 AND space_id IS NULL AND status='open'
ORDER BY started_at DESC LIMIT 1`,
[agent_id]
);
if (existing) return existing;
const { rows: [r] } = await pool.query(
`INSERT INTO conversations(title, agent_id, metadata) VALUES($1,$2,$3) RETURNING *`,
[null, agent_id, {}]
);
await recordAudit(actor, 'create', 'conversation', r.id, null, r);
return r;
}
export async function findOrCreateForSpace(space_id, agent_id, actor) {
const { rows: [existing] } = await pool.query(
`SELECT * FROM conversations

View File

@@ -0,0 +1,19 @@
import { describe, it, expect, beforeAll } from 'vitest';
import { resetDb } from '../helpers/db.js';
import { migrateUp } from '../../lib/db/migrate.js';
import * as agents from '../../lib/db/repos/agents.js';
import * as conversations from '../../lib/db/repos/conversations.js';
const owner = { kind: 'user', id: null };
beforeAll(async () => { await resetDb(); await migrateUp(); });
describe('findOrCreateGlobal', () => {
it('creates one space-less open conversation and reuses it', async () => {
const y = await agents.getBySlug('yerin'); // seeded by 011_yerin.sql
const c1 = await conversations.findOrCreateGlobal(y.id, owner);
expect(c1.space_id).toBeNull();
expect(c1.agent_id).toBe(y.id);
const c2 = await conversations.findOrCreateGlobal(y.id, owner);
expect(c2.id).toBe(c1.id);
});
});