There is no public media any more. `/media/public/<id>` served a media row with no session at all, so anyone with the id could read a file. The public/private split is gone: the path is `/media/<id>` (and `/media/<id>/thumbnail`), every request is signed in first, and `grabUserMedia` decides whether the user may see it: their own upload, a bot's or workspace's picture or file they reach, or a file on a task they reach. Anything else is a 404 before a path is built. The `media.is_private` column and the two per-user directories went with it: uploads live in `media/<user_id>/` and there is nothing to pick between. The files browser's media volume is now the viewer's own folder whatever their role. Bots also say which of the two things they mean. A `[file:ID]` ref is a saved file and its chip opens the bytes; a folder is a new `[folder:volume:owner:path]` ref (`src/utils/folder-ref.ts`) whose chip opens the files browser there and downloads nothing. The old `[path:...]` ref and the extension sniffing that guessed file from folder are gone, so `import_file` names the folder holding a file it copied rather than the file itself. The prompts say what the Assistant got wrong: list before importing or saving, one copy per artifact, never split a file into parts unless asked, never claim the store is empty without a fresh list, and never invent a size cap. A re-import now says the path already existed instead of silently overwriting and reporting a fresh copy.
150 lines
5.1 KiB
TypeScript
150 lines
5.1 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import botMessagesToHarness from "./bot-messages-to-harness";
|
|
|
|
const message = (author: "user" | "bot", text: string) => ({ author, text });
|
|
|
|
describe("botMessagesToHarness", () => {
|
|
test("maps authors to roles", () => {
|
|
expect(
|
|
botMessagesToHarness({
|
|
messages: [message("user", "hi"), message("bot", "hello")],
|
|
}),
|
|
).toEqual([
|
|
{ role: "user", content: "hi" },
|
|
{ role: "assistant", content: "hello" },
|
|
]);
|
|
});
|
|
|
|
test("joins back-to-back messages from one side", () => {
|
|
expect(
|
|
botMessagesToHarness({
|
|
messages: [message("user", "one"), message("user", "two")],
|
|
}),
|
|
).toEqual([{ role: "user", content: "one\n\ntwo" }]);
|
|
});
|
|
|
|
test("starts with the user and skips empty messages", () => {
|
|
expect(
|
|
botMessagesToHarness({
|
|
messages: [
|
|
message("bot", "welcome"),
|
|
message("user", " "),
|
|
message("user", "hi"),
|
|
],
|
|
}),
|
|
).toEqual([{ role: "user", content: "hi" }]);
|
|
});
|
|
});
|
|
|
|
describe("botMessagesToHarness with replies", () => {
|
|
test("quotes what a user message answers", () => {
|
|
expect(
|
|
botMessagesToHarness({
|
|
messages: [
|
|
{ author: "user", text: "hi" },
|
|
{ author: "bot", text: "The report is ready." },
|
|
{
|
|
author: "user",
|
|
text: "Great, send it over.",
|
|
reply_to: { id: 4, author: "bot", text: "The report is ready." },
|
|
},
|
|
],
|
|
}),
|
|
).toEqual([
|
|
{ role: "user", content: "hi" },
|
|
{ role: "assistant", content: "The report is ready." },
|
|
{
|
|
role: "user",
|
|
content: `[Replying to your earlier message: "The report is ready."]\n\nGreat, send it over.`,
|
|
},
|
|
]);
|
|
});
|
|
|
|
test("says a quoted file-only message was a file", () => {
|
|
expect(
|
|
botMessagesToHarness({
|
|
messages: [
|
|
{
|
|
author: "user",
|
|
text: "What was that?",
|
|
reply_to: { id: 5, author: "user", text: "" },
|
|
},
|
|
],
|
|
}),
|
|
).toEqual([
|
|
{
|
|
role: "user",
|
|
content: `[Replying to the user's own earlier message: "(a file)"]\n\nWhat was that?`,
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("botMessagesToHarness with a file-only reply", () => {
|
|
test("keeps the quote when the reply has no text", () => {
|
|
expect(
|
|
botMessagesToHarness({
|
|
messages: [
|
|
{
|
|
id: 7,
|
|
author: "user",
|
|
text: "",
|
|
reply_to: { id: 4, author: "bot", text: "Send me the logo." },
|
|
attachments: [{ id: 9, name: "logo.png", media_type: "image", url: "/media/9" }],
|
|
},
|
|
],
|
|
}),
|
|
).toEqual([
|
|
{
|
|
role: "user",
|
|
content: `[Replying to your earlier message: "Send me the logo."]\n\n[Attached earlier: "logo.png"]`,
|
|
},
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("botMessagesToHarness with files", () => {
|
|
const attachments = [{ id: 9, name: "shot.png", media_type: "image" as const, url: "/media/9" }];
|
|
|
|
test("puts a message's loaded files after its text", () => {
|
|
const parts = new Map([[1, [{ type: "image" as const, url: "data:image/jpeg;base64,AA", name: "shot.png" }]]]);
|
|
|
|
expect(
|
|
botMessagesToHarness({
|
|
messages: [{ id: 1, author: "user", text: "What's this?", attachments }],
|
|
parts,
|
|
}),
|
|
).toEqual([
|
|
{
|
|
role: "user",
|
|
content: [
|
|
{ type: "text", text: "What's this?" },
|
|
{ type: "image", url: "data:image/jpeg;base64,AA", name: "shot.png" },
|
|
],
|
|
},
|
|
]);
|
|
});
|
|
|
|
test("names files it didn't load, and keeps a file-only message", () => {
|
|
expect(
|
|
botMessagesToHarness({
|
|
messages: [{ id: 2, author: "user", text: "", attachments }],
|
|
}),
|
|
).toEqual([{ role: "user", content: `[Attached earlier: "shot.png"]` }]);
|
|
});
|
|
});
|
|
|
|
describe("botMessagesToHarness with mentions", () => {
|
|
test("names the bots and workspaces a user message mentions", () => {
|
|
expect(
|
|
botMessagesToHarness({
|
|
messages: [message("user", "ask [bot:3]"), message("bot", "[bot:3] is on it")],
|
|
refs: { bots: new Map([[3, { name: "Ada" }]]), workspaces: new Map() },
|
|
}),
|
|
).toEqual([
|
|
{ role: "user", content: "ask [bot:3]\n\n[Mentions: [bot:3] is Ada]" },
|
|
{ role: "assistant", content: "[bot:3] is on it" },
|
|
]);
|
|
});
|
|
});
|