cloudaxe-opencode/packages/opencode/src/v2/session/storage.ts
2026-05-20 20:12:30 -04:00

100 lines
3.5 KiB
TypeScript

import { WorkspaceID } from "@/control-plane/schema"
import { ProjectID } from "@/project/schema"
import { SessionID } from "@/session/schema"
import { V2Schema } from "@opencode-ai/core/v2-schema"
import { SessionMessage } from "@opencode-ai/core/session-message"
import { ModelV2 } from "@opencode-ai/core/model"
import { Context, Effect, Schema } from "effect"
export const SortOrder = Schema.Literals(["asc", "desc"]).annotate({
identifier: "SortOrder",
})
export type SortOrder = typeof SortOrder.Type
export const PageDirection = Schema.Literals(["previous", "next"]).annotate({
identifier: "PageDirection",
})
export type PageDirection = typeof PageDirection.Type
export class StorageError extends Schema.TaggedErrorClass<StorageError>()("StorageError", {
message: Schema.String,
cause: Schema.Defect,
}) {}
export class SessionRow extends Schema.Class<SessionRow>("SessionRow")({
id: SessionID,
parentID: Schema.optional(SessionID),
projectID: ProjectID,
workspaceID: Schema.optional(WorkspaceID),
directory: Schema.optional(Schema.String),
path: Schema.optional(Schema.String),
agent: Schema.optional(Schema.String),
model: Schema.optional(ModelV2.Ref),
cost: Schema.Finite,
tokens: Schema.Struct({
input: Schema.Finite,
output: Schema.Finite,
reasoning: Schema.Finite,
cache: Schema.Struct({
read: Schema.Finite,
write: Schema.Finite,
}),
}),
time: Schema.Struct({
created: V2Schema.DateTimeUtcFromMillis,
updated: V2Schema.DateTimeUtcFromMillis,
archived: Schema.optional(V2Schema.DateTimeUtcFromMillis),
}),
title: Schema.String,
}) {}
export const SessionCursor = Schema.Struct({
id: SessionID,
time: Schema.Finite,
direction: PageDirection,
}).annotate({ identifier: "SessionCursor" })
export type SessionCursor = typeof SessionCursor.Type
export const SessionListInput = Schema.Struct({
limit: Schema.optional(Schema.Finite),
order: Schema.optional(SortOrder),
directory: Schema.optional(Schema.String),
path: Schema.optional(Schema.String),
workspaceID: Schema.optional(WorkspaceID),
roots: Schema.optional(Schema.Boolean),
start: Schema.optional(Schema.Finite),
search: Schema.optional(Schema.String),
cursor: Schema.optional(SessionCursor),
}).annotate({ identifier: "SessionListInput" })
export type SessionListInput = typeof SessionListInput.Type
export const MessageCursor = Schema.Struct({
id: SessionMessage.ID,
time: Schema.Finite,
direction: PageDirection,
}).annotate({ identifier: "MessageCursor" })
export type MessageCursor = typeof MessageCursor.Type
export const MessageListInput = Schema.Struct({
sessionID: SessionID,
limit: Schema.optional(Schema.Finite),
order: Schema.optional(SortOrder),
cursor: Schema.optional(MessageCursor),
}).annotate({ identifier: "MessageListInput" })
export type MessageListInput = typeof MessageListInput.Type
export interface Interface {
readonly get: (sessionID: SessionID) => Effect.Effect<SessionRow | undefined, StorageError>
readonly list: (input: SessionListInput) => Effect.Effect<SessionRow[], StorageError>
readonly messages: (input: MessageListInput) => Effect.Effect<SessionMessage.Message[], StorageError>
readonly context: (sessionID: SessionID) => Effect.Effect<SessionMessage.Message[], StorageError>
}
export function pageOrder(order: SortOrder, direction: PageDirection) {
if (direction !== "previous") return order
return order === "asc" ? "desc" : "asc"
}
export class Service extends Context.Service<Service, Interface>()("@opencode/v2/session/Storage") {}
export * as SessionStorage from "./storage"