mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-13 19:46:16 +03:00
fix(core): transfer only settled history (#44008)
This commit is contained in:
committed by
GitHub
Unverified
parent
2937f0e635
commit
fb703ede73
@@ -53,7 +53,7 @@ const layer = Layer.effect(
|
||||
export: Effect.fn("SessionTransfer.export")(function* (input) {
|
||||
const data = {
|
||||
info: yield* sessions.get(input.sessionID),
|
||||
messages: yield* sessions.messages({ sessionID: input.sessionID, order: "asc" }),
|
||||
messages: (yield* sessions.messages({ sessionID: input.sessionID, order: "asc" })).filter(isSettled),
|
||||
}
|
||||
return input.sanitize ? sanitize(data) : data
|
||||
}),
|
||||
@@ -68,7 +68,7 @@ const layer = Layer.effect(
|
||||
if (recorded) return yield* new ImportConflictError({ sessionID })
|
||||
const project = yield* projects.resolve(input.location.directory)
|
||||
yield* upsertProject(db, project).pipe(Effect.orDie)
|
||||
const messages = input.data.messages.map((message, index) => {
|
||||
const messages = input.data.messages.filter(isSettled).map((message, index) => {
|
||||
const encoded = encodeMessage(message)
|
||||
const { id: _, type, ...data } = encoded
|
||||
return {
|
||||
@@ -144,6 +144,12 @@ export const node = makeGlobalNode({
|
||||
deps: [App.node, Bus.node, Database.node, Project.node, Session.node],
|
||||
})
|
||||
|
||||
function isSettled(message: SessionMessage.Info) {
|
||||
if (message.type === "assistant") return message.time.completed !== undefined
|
||||
if (message.type === "shell" || message.type === "compaction") return message.status !== "running"
|
||||
return true
|
||||
}
|
||||
|
||||
function redact(kind: string, id: string, value: string) {
|
||||
return value.trim() ? `[redacted:${kind}:${id}]` : value
|
||||
}
|
||||
|
||||
@@ -931,6 +931,134 @@ describe("Session.create", () => {
|
||||
})
|
||||
|
||||
describe("SessionTransfer", () => {
|
||||
it.effect("exports only settled projected messages", () =>
|
||||
Effect.gen(function* () {
|
||||
const session = yield* Session.Service
|
||||
const transfer = yield* SessionTransfer.Service
|
||||
const bus = yield* Bus.Service
|
||||
const { db } = yield* Database.Service
|
||||
const source = yield* session.create({ location })
|
||||
yield* session.prompt({ sessionID: source.id, text: "Settled", resume: false })
|
||||
yield* SessionInbox.promote(db, bus, source.id, "steer")
|
||||
yield* bus.publish(SessionEvent.Step.Started, {
|
||||
sessionID: source.id,
|
||||
assistantMessageID: SessionMessage.ID.create(),
|
||||
agent: Agent.ID.make("build"),
|
||||
model: Model.Ref.make({ id: Model.ID.make("model"), providerID: Provider.ID.make("provider") }),
|
||||
})
|
||||
yield* bus.publish(SessionEvent.Shell.Started, {
|
||||
sessionID: source.id,
|
||||
shell: Shell.Info.make({
|
||||
id: Shell.ID.make("sh_transfer_export"),
|
||||
status: "running",
|
||||
command: "sleep 10",
|
||||
cwd: location.directory,
|
||||
shell: "/bin/sh",
|
||||
file: "/tmp/sh_transfer_export.out",
|
||||
metadata: {},
|
||||
time: { started: 0 },
|
||||
}),
|
||||
})
|
||||
yield* bus.publish(SessionEvent.Compaction.Started, {
|
||||
sessionID: source.id,
|
||||
reason: "manual",
|
||||
recent: "pending",
|
||||
})
|
||||
|
||||
expect((yield* transfer.export({ sessionID: source.id })).messages).toMatchObject([
|
||||
{ type: "user", text: "Settled" },
|
||||
])
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("imports only settled projected messages", () =>
|
||||
Effect.gen(function* () {
|
||||
const session = yield* Session.Service
|
||||
const transfer = yield* SessionTransfer.Service
|
||||
const { db } = yield* Database.Service
|
||||
const template = yield* session.create({ location, title: "Transfer source" })
|
||||
const sessionID = Session.ID.create()
|
||||
const userID = SessionMessage.ID.create()
|
||||
const runningAssistantID = SessionMessage.ID.create()
|
||||
const completedAssistantID = SessionMessage.ID.create()
|
||||
const runningShellID = SessionMessage.ID.create()
|
||||
const completedShellID = SessionMessage.ID.create()
|
||||
const runningCompactionID = SessionMessage.ID.create()
|
||||
const completedCompactionID = SessionMessage.ID.create()
|
||||
const model = Model.Ref.make({ id: Model.ID.make("model"), providerID: Provider.ID.make("provider") })
|
||||
|
||||
yield* transfer.import({
|
||||
data: {
|
||||
info: { ...template, id: sessionID },
|
||||
messages: [
|
||||
{ id: userID, type: "user", text: "Settled", time: { created: DateTime.makeUnsafe(1) } },
|
||||
{
|
||||
id: runningAssistantID,
|
||||
type: "assistant",
|
||||
agent: Agent.ID.make("build"),
|
||||
model,
|
||||
content: [],
|
||||
time: { created: DateTime.makeUnsafe(2) },
|
||||
},
|
||||
{
|
||||
id: completedAssistantID,
|
||||
type: "assistant",
|
||||
agent: Agent.ID.make("build"),
|
||||
model,
|
||||
content: [],
|
||||
time: { created: DateTime.makeUnsafe(3), completed: DateTime.makeUnsafe(4) },
|
||||
},
|
||||
{
|
||||
id: runningShellID,
|
||||
type: "shell",
|
||||
shellID: Shell.ID.make("sh_transfer_running"),
|
||||
command: "sleep 10",
|
||||
status: "running",
|
||||
time: { created: DateTime.makeUnsafe(5) },
|
||||
},
|
||||
{
|
||||
id: completedShellID,
|
||||
type: "shell",
|
||||
shellID: Shell.ID.make("sh_transfer_completed"),
|
||||
command: "pwd",
|
||||
status: "exited",
|
||||
exit: 0,
|
||||
output: { output: "/project", cursor: 8, size: 8, truncated: false },
|
||||
time: { created: DateTime.makeUnsafe(6), completed: DateTime.makeUnsafe(7) },
|
||||
},
|
||||
{
|
||||
id: runningCompactionID,
|
||||
type: "compaction",
|
||||
status: "running",
|
||||
reason: "manual",
|
||||
summary: "pending",
|
||||
recent: "pending",
|
||||
time: { created: DateTime.makeUnsafe(8) },
|
||||
},
|
||||
{
|
||||
id: completedCompactionID,
|
||||
type: "compaction",
|
||||
status: "completed",
|
||||
reason: "manual",
|
||||
summary: "summary",
|
||||
recent: "recent",
|
||||
time: { created: DateTime.makeUnsafe(9) },
|
||||
},
|
||||
],
|
||||
},
|
||||
location,
|
||||
})
|
||||
|
||||
expect((yield* session.messages({ sessionID, order: "asc" })).map((message) => message.id)).toEqual([
|
||||
userID,
|
||||
completedAssistantID,
|
||||
completedShellID,
|
||||
completedCompactionID,
|
||||
])
|
||||
expect(yield* Bus.latestSequence(db, sessionID)).toBe(4)
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("imports projected messages and reserves their aggregate sequence", () =>
|
||||
Effect.gen(function* () {
|
||||
const session = yield* Session.Service
|
||||
|
||||
Reference in New Issue
Block a user