134 lines
4.0 KiB
TypeScript
134 lines
4.0 KiB
TypeScript
/**
|
|
* Smoke test: buildSystemPrompt injects "## Subscribed Notes" when the
|
|
* job owner has inject-mode subscriptions, and omits it when they don't.
|
|
*/
|
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
import Database from 'better-sqlite3';
|
|
import { mkdtempSync, rmSync } from 'fs';
|
|
import { tmpdir } from 'os';
|
|
import { join } from 'path';
|
|
import { runMigrations } from '../db/migrate.js';
|
|
import { NotesRepository } from '../notes/notes-repository.js';
|
|
import { NotesService } from '../notes/notes-service.js';
|
|
import { buildSystemPrompt, type NotesInjectContext, type Movement } from './agent-loop.js';
|
|
import { DEFAULT_NOTES_INJECT } from '../config.js';
|
|
|
|
function makeMovement(): Movement {
|
|
return {
|
|
name: 'investigate',
|
|
persona: 'investigator',
|
|
instruction: 'do the thing',
|
|
rules: [{ condition: 'done', next: 'plan' }],
|
|
allowedTools: [],
|
|
edit: false,
|
|
};
|
|
}
|
|
|
|
describe('buildSystemPrompt — notes inject section', () => {
|
|
let tmpRoot: string;
|
|
let db: Database.Database;
|
|
let service: NotesService;
|
|
|
|
const aliceUser = {
|
|
id: 'alice',
|
|
role: 'user' as const,
|
|
orgIds: [] as string[],
|
|
email: 'alice@example.com',
|
|
name: 'Alice',
|
|
avatarUrl: null,
|
|
status: 'active' as const,
|
|
defaultVisibility: 'private' as const,
|
|
defaultVisibilityOrgId: null,
|
|
};
|
|
|
|
const bobPublisher = { id: 'bob', role: 'user' as const, orgIds: [] as string[] };
|
|
|
|
beforeEach(() => {
|
|
tmpRoot = mkdtempSync(join(tmpdir(), 'al-notes-test-'));
|
|
db = new Database(join(tmpRoot, 'test.db'));
|
|
runMigrations(db);
|
|
db.prepare(
|
|
`INSERT INTO users (id, email, name) VALUES ('alice','alice@example.com','Alice'),('bob','bob@example.com','Bob')`
|
|
).run();
|
|
const repo = new NotesRepository(db);
|
|
service = new NotesService({
|
|
db,
|
|
repo,
|
|
userFolderRoot: tmpRoot,
|
|
getUserOrgIds: () => [],
|
|
});
|
|
});
|
|
|
|
afterEach(() => {
|
|
db.close();
|
|
rmSync(tmpRoot, { recursive: true, force: true });
|
|
});
|
|
|
|
it('omits ## Subscribed Notes when user has no inject subscriptions', () => {
|
|
const prompt = buildSystemPrompt(
|
|
makeMovement(),
|
|
1, 5, [], undefined, null,
|
|
'alice', undefined, undefined, null, undefined,
|
|
undefined, // no notesCtx
|
|
);
|
|
expect(prompt).not.toContain('## Subscribed Notes');
|
|
});
|
|
|
|
it('includes ## Subscribed Notes when inject subscription exists', () => {
|
|
// alice publishes a public note
|
|
service.writeNote({
|
|
ownerId: 'alice',
|
|
folder: 'runbooks',
|
|
fileName: 'deploy.md',
|
|
content: '---\nvisibility: public\n---\nDeploy checklist step 1',
|
|
});
|
|
// bob subscribes to alice's note in inject mode — alice is the consumer here
|
|
// Actually let's have alice subscribe to bob's note:
|
|
service.writeNote({
|
|
ownerId: 'bob',
|
|
folder: 'tips',
|
|
fileName: 'shortcuts.md',
|
|
content: '---\nvisibility: public\n---\nUseful shortcuts: Ctrl+C',
|
|
});
|
|
service.upsertSubscription({
|
|
consumerUser: aliceUser as Express.User,
|
|
publisherUserId: 'bob',
|
|
folder: 'tips',
|
|
mode: 'inject',
|
|
enabled: 1,
|
|
});
|
|
|
|
const notesCtx: NotesInjectContext = {
|
|
service,
|
|
config: DEFAULT_NOTES_INJECT,
|
|
user: aliceUser,
|
|
};
|
|
|
|
const prompt = buildSystemPrompt(
|
|
makeMovement(),
|
|
1, 5, [], undefined, null,
|
|
'alice', undefined, undefined, null, undefined,
|
|
notesCtx,
|
|
);
|
|
expect(prompt).toContain('## Subscribed Notes');
|
|
expect(prompt).toContain('shortcuts.md');
|
|
expect(prompt).toContain('Useful shortcuts: Ctrl+C');
|
|
});
|
|
|
|
it('does not include section when notesCtx is provided but subscriptions are empty', () => {
|
|
const notesCtx: NotesInjectContext = {
|
|
service,
|
|
config: DEFAULT_NOTES_INJECT,
|
|
user: aliceUser,
|
|
};
|
|
|
|
const prompt = buildSystemPrompt(
|
|
makeMovement(),
|
|
1, 5, [], undefined, null,
|
|
'alice', undefined, undefined, null, undefined,
|
|
notesCtx,
|
|
);
|
|
expect(prompt).not.toContain('## Subscribed Notes');
|
|
});
|
|
});
|