mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-11 22:50:06 +00:00
chore: Fix seed assistant threads so the assistant page can list them (no-changelog) (#37863)
Co-authored-by: Claude Fable 5.1 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
bbc8e83e5d
commit
5cfae1ce62
@@ -298,12 +298,20 @@ function main() {
|
||||
// workflow, so a "what was I working on?" probe has something to find.
|
||||
const threadId = uuid();
|
||||
const threadAt = NOW - Math.floor(random() * DAYS * 86400e3);
|
||||
// `resourceId` is the owning user: the assistant page lists threads by it, so a
|
||||
// workflow id here makes the thread exist but never show. The workflow goes in
|
||||
// `sourceContext`, where the runtime also puts it.
|
||||
insThread.run(
|
||||
threadId,
|
||||
wf.id,
|
||||
user.id,
|
||||
project.id,
|
||||
`Working on ${short}`,
|
||||
`{${THREAD_MARKER}}`,
|
||||
JSON.stringify({
|
||||
seeded: true,
|
||||
source: 'assistant_page',
|
||||
origin: 'internal',
|
||||
sourceContext: { workflowId: wf.id },
|
||||
}),
|
||||
iso(threadAt),
|
||||
iso(threadAt + 600e3),
|
||||
);
|
||||
@@ -329,16 +337,20 @@ function main() {
|
||||
`Added a Data Table insert named "Record Run" at the end of ${short}, writing to \`automation_runs\`, matching the other workflows here.`,
|
||||
],
|
||||
];
|
||||
for (const [role, content] of turns) {
|
||||
// `content` holds the whole agent message as JSON, the way the runtime stores it.
|
||||
// A plain string is dropped on read, so the thread would open empty.
|
||||
for (const [i, [role, text]] of turns.entries()) {
|
||||
const messageId = uuid();
|
||||
const createdAt = iso(threadAt + i * 30e3);
|
||||
insMessage.run(
|
||||
uuid(),
|
||||
messageId,
|
||||
threadId,
|
||||
content,
|
||||
JSON.stringify({ id: messageId, role, content: [{ type: 'text', text }], createdAt }),
|
||||
role,
|
||||
'message',
|
||||
wf.id,
|
||||
iso(threadAt),
|
||||
iso(threadAt),
|
||||
null,
|
||||
user.id,
|
||||
createdAt,
|
||||
createdAt,
|
||||
);
|
||||
msgCount++;
|
||||
}
|
||||
|
||||
@@ -192,6 +192,40 @@ describe('seedHistory cleanup', () => {
|
||||
assert.ok(c.seededActivity > 0, 'activity written');
|
||||
});
|
||||
|
||||
// The assistant page lists threads by `resourceId = user id` and drops any message
|
||||
// whose `content` is not an agent-message JSON object, so both must match the runtime.
|
||||
it('writes threads and messages the assistant page can read', () => {
|
||||
const dbFile = fixture();
|
||||
run(dbFile);
|
||||
const db = new DatabaseSync(dbFile, { readOnly: true });
|
||||
const threads = db
|
||||
.prepare(
|
||||
`SELECT resourceId FROM instance_ai_threads WHERE metadata LIKE '%"seeded":true%' AND projectId = 'p-seed'`,
|
||||
)
|
||||
.all();
|
||||
assert.ok(threads.length > 0);
|
||||
assert.ok(
|
||||
threads.every((t) => t.resourceId === 'u1'),
|
||||
'threads owned by the first user',
|
||||
);
|
||||
const messages = db
|
||||
.prepare(
|
||||
`SELECT m.content, m.resourceId, m.type FROM instance_ai_messages m
|
||||
JOIN instance_ai_threads t ON t.id = m.threadId
|
||||
WHERE t.metadata LIKE '%"seeded":true%' AND t.projectId = 'p-seed'`,
|
||||
)
|
||||
.all();
|
||||
assert.ok(messages.length > 0);
|
||||
for (const m of messages) {
|
||||
assert.equal(m.resourceId, 'u1');
|
||||
assert.equal(m.type, null);
|
||||
const parsed = JSON.parse(m.content);
|
||||
assert.ok(['user', 'assistant'].includes(parsed.role));
|
||||
assert.equal(parsed.content[0].type, 'text');
|
||||
}
|
||||
db.close();
|
||||
});
|
||||
|
||||
it('leaves rows it did not create alone', () => {
|
||||
const dbFile = fixture();
|
||||
run(dbFile);
|
||||
|
||||
Reference in New Issue
Block a user