mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-03-30 13:54:01 +00:00
- Rename packages/opencode → packages/tfcode (directory only) - Rename bin/opencode → bin/tfcode (CLI binary) - Rename .opencode → .tfcode (config directory) - Update package.json name and bin field - Update config directory path references (.tfcode) - Keep internal code references as 'opencode' for easy upstream sync - Keep @opencode-ai/* workspace package names This minimal branding approach allows clean merges from upstream opencode repository while providing tfcode branding for users.
120 lines
3.8 KiB
TypeScript
120 lines
3.8 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import path from "path"
|
|
import { Instance } from "../../src/project/instance"
|
|
import { Server } from "../../src/server/server"
|
|
import { Session } from "../../src/session"
|
|
import { MessageV2 } from "../../src/session/message-v2"
|
|
import { MessageID, PartID, type SessionID } from "../../src/session/schema"
|
|
import { Log } from "../../src/util/log"
|
|
|
|
const root = path.join(__dirname, "../..")
|
|
Log.init({ print: false })
|
|
|
|
async function fill(sessionID: SessionID, count: number, time = (i: number) => Date.now() + i) {
|
|
const ids = [] as MessageID[]
|
|
for (let i = 0; i < count; i++) {
|
|
const id = MessageID.ascending()
|
|
ids.push(id)
|
|
await Session.updateMessage({
|
|
id,
|
|
sessionID,
|
|
role: "user",
|
|
time: { created: time(i) },
|
|
agent: "test",
|
|
model: { providerID: "test", modelID: "test" },
|
|
tools: {},
|
|
mode: "",
|
|
} as unknown as MessageV2.Info)
|
|
await Session.updatePart({
|
|
id: PartID.ascending(),
|
|
sessionID,
|
|
messageID: id,
|
|
type: "text",
|
|
text: `m${i}`,
|
|
})
|
|
}
|
|
return ids
|
|
}
|
|
|
|
describe("session messages endpoint", () => {
|
|
test("returns cursor headers for older pages", async () => {
|
|
await Instance.provide({
|
|
directory: root,
|
|
fn: async () => {
|
|
const session = await Session.create({})
|
|
const ids = await fill(session.id, 5)
|
|
const app = Server.Default()
|
|
|
|
const a = await app.request(`/session/${session.id}/message?limit=2`)
|
|
expect(a.status).toBe(200)
|
|
const aBody = (await a.json()) as MessageV2.WithParts[]
|
|
expect(aBody.map((item) => item.info.id)).toEqual(ids.slice(-2))
|
|
const cursor = a.headers.get("x-next-cursor")
|
|
expect(cursor).toBeTruthy()
|
|
expect(a.headers.get("link")).toContain('rel="next"')
|
|
|
|
const b = await app.request(`/session/${session.id}/message?limit=2&before=${encodeURIComponent(cursor!)}`)
|
|
expect(b.status).toBe(200)
|
|
const bBody = (await b.json()) as MessageV2.WithParts[]
|
|
expect(bBody.map((item) => item.info.id)).toEqual(ids.slice(-4, -2))
|
|
|
|
await Session.remove(session.id)
|
|
},
|
|
})
|
|
})
|
|
|
|
test("keeps full-history responses when limit is omitted", async () => {
|
|
await Instance.provide({
|
|
directory: root,
|
|
fn: async () => {
|
|
const session = await Session.create({})
|
|
const ids = await fill(session.id, 3)
|
|
const app = Server.Default()
|
|
|
|
const res = await app.request(`/session/${session.id}/message`)
|
|
expect(res.status).toBe(200)
|
|
const body = (await res.json()) as MessageV2.WithParts[]
|
|
expect(body.map((item) => item.info.id)).toEqual(ids)
|
|
|
|
await Session.remove(session.id)
|
|
},
|
|
})
|
|
})
|
|
|
|
test("rejects invalid cursors and missing sessions", async () => {
|
|
await Instance.provide({
|
|
directory: root,
|
|
fn: async () => {
|
|
const session = await Session.create({})
|
|
const app = Server.Default()
|
|
|
|
const bad = await app.request(`/session/${session.id}/message?limit=2&before=bad`)
|
|
expect(bad.status).toBe(400)
|
|
|
|
const miss = await app.request(`/session/ses_missing/message?limit=2`)
|
|
expect(miss.status).toBe(404)
|
|
|
|
await Session.remove(session.id)
|
|
},
|
|
})
|
|
})
|
|
|
|
test("does not truncate large legacy limit requests", async () => {
|
|
await Instance.provide({
|
|
directory: root,
|
|
fn: async () => {
|
|
const session = await Session.create({})
|
|
await fill(session.id, 520)
|
|
const app = Server.Default()
|
|
|
|
const res = await app.request(`/session/${session.id}/message?limit=510`)
|
|
expect(res.status).toBe(200)
|
|
const body = (await res.json()) as MessageV2.WithParts[]
|
|
expect(body).toHaveLength(510)
|
|
|
|
await Session.remove(session.id)
|
|
},
|
|
})
|
|
})
|
|
})
|