Something went wrong. Try again.
opencode v2 mirror
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677export * as SessionV1 from "./session.js"
import { Effect, Schema, Types } from "effect"import { durable, ephemeral, inventory } from "../event.js"import { Project } from "../project.js"import { Provider } from "../provider.js"import { Model } from "../model.js"import { NonNegativeInt, optional, statics } from "../schema.js"import { ascending } from "../identifier.js"import { SessionID } from "../session-id.js"import { WorkspaceID } from "../workspace-id.js"import { PermissionV1 } from "./permission.js"import { FileDiff } from "../file-diff.js"
const Timestamp = Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0))
export const MessageID = Schema.String.check(Schema.isStartsWith("msg")).pipe( Schema.brand("SessionV1.MessageID"), statics((schema) => ({ ascending: (id?: string) => schema.make(id ?? "msg_" + ascending()) })),)export type MessageID = typeof MessageID.Type
export const PartID = Schema.String.check(Schema.isStartsWith("prt")).pipe( Schema.brand("SessionV1.PartID"), statics((schema) => ({ ascending: (id?: string) => schema.make(id ?? "prt_" + ascending()) })),)export type PartID = typeof PartID.Type
const namedError = <Name extends string, Fields extends Schema.Struct.Fields>(name: Name, fields: Fields) => { const schema = Schema.Struct({ name: Schema.Literal(name), data: Schema.Struct(fields) }).annotate({ identifier: name, }) return { Schema: schema, EffectSchema: schema }}
export const OutputLengthError = namedError("MessageOutputLengthError", {})
export const AuthError = namedError("ProviderAuthError", { providerID: Schema.String, message: Schema.String,})
export const AbortedError = namedError("MessageAbortedError", { message: Schema.String })export const StructuredOutputError = namedError("StructuredOutputError", { message: Schema.String, retries: NonNegativeInt,})export const APIError = namedError("APIError", { message: Schema.String, statusCode: Schema.optional(NonNegativeInt), isRetryable: Schema.Boolean, responseHeaders: Schema.optional(Schema.Record(Schema.String, Schema.String)), responseBody: Schema.optional(Schema.String), metadata: Schema.optional(Schema.Record(Schema.String, Schema.String)),})export type APIError = Schema.Schema.Type<typeof APIError.Schema>export const ContextOverflowError = namedError("ContextOverflowError", { message: Schema.String, responseBody: Schema.optional(Schema.String),})export const ContentFilterError = namedError("ContentFilterError", { message: Schema.String,})
export class OutputFormatText extends Schema.Class<OutputFormatText>("OutputFormatText")({ type: Schema.Literal("text"),}) {}
export class OutputFormatJsonSchema extends Schema.Class<OutputFormatJsonSchema>("OutputFormatJsonSchema")({ type: Schema.Literal("json_schema"), schema: Schema.Record(Schema.String, Schema.Any).annotate({ identifier: "SessionV1.JSONSchema" }), retryCount: NonNegativeInt.pipe(Schema.optional, Schema.withDecodingDefault(Effect.succeed(2))),}) {}
export const Format = Schema.Union([OutputFormatText, OutputFormatJsonSchema]).annotate({ discriminator: "type", identifier: "SessionV1.OutputFormat",})export type OutputFormat = Schema.Schema.Type<typeof Format>
const partBase = { id: PartID, sessionID: SessionID, messageID: MessageID,}
export const SnapshotPart = Schema.Struct({ ...partBase, type: Schema.Literal("snapshot"), snapshot: Schema.String,}).annotate({ identifier: "SessionV1.SnapshotPart" })export type SnapshotPart = Types.DeepMutable<Schema.Schema.Type<typeof SnapshotPart>>
export const PatchPart = Schema.Struct({ ...partBase, type: Schema.Literal("patch"), hash: Schema.String, files: Schema.Array(Schema.String),}).annotate({ identifier: "SessionV1.PatchPart" })export type PatchPart = Types.DeepMutable<Schema.Schema.Type<typeof PatchPart>>
export const TextPart = Schema.Struct({ ...partBase, type: Schema.Literal("text"), text: Schema.String, synthetic: Schema.optional(Schema.Boolean), ignored: Schema.optional(Schema.Boolean), time: Schema.optional( Schema.Struct({ start: NonNegativeInt, end: Schema.optional(NonNegativeInt), }), ), metadata: Schema.optional(Schema.Record(Schema.String, Schema.Any)),}).annotate({ identifier: "SessionV1.TextPart" })export type TextPart = Types.DeepMutable<Schema.Schema.Type<typeof TextPart>>
export const ReasoningPart = Schema.Struct({ ...partBase, type: Schema.Literal("reasoning"), text: Schema.String, metadata: Schema.optional(Schema.Record(Schema.String, Schema.Any)), time: Schema.Struct({ start: NonNegativeInt, end: Schema.optional(NonNegativeInt), }),}).annotate({ identifier: "SessionV1.ReasoningPart" })export type ReasoningPart = Types.DeepMutable<Schema.Schema.Type<typeof ReasoningPart>>
const filePartSourceBase = { text: Schema.Struct({ value: Schema.String, start: Schema.Finite, end: Schema.Finite, }).annotate({ identifier: "SessionV1.FilePartSourceText" }),}
export const Range = Schema.Struct({ start: Schema.Struct({ line: NonNegativeInt, character: NonNegativeInt }), end: Schema.Struct({ line: NonNegativeInt, character: NonNegativeInt }),}).annotate({ identifier: "SessionV1.Range" })export type Range = typeof Range.Type
export const FileSource = Schema.Struct({ ...filePartSourceBase, type: Schema.Literal("file"), path: Schema.String,}).annotate({ identifier: "SessionV1.FileSource" })
export const SymbolSource = Schema.Struct({ ...filePartSourceBase, type: Schema.Literal("symbol"), path: Schema.String, range: Range, name: Schema.String, kind: NonNegativeInt,}).annotate({ identifier: "SessionV1.SymbolSource" })
export const ResourceSource = Schema.Struct({ ...filePartSourceBase, type: Schema.Literal("resource"), clientName: Schema.String, uri: Schema.String,}).annotate({ identifier: "SessionV1.ResourceSource" })
export const FilePartSource = Schema.Union([FileSource, SymbolSource, ResourceSource]).annotate({ discriminator: "type", identifier: "SessionV1.FilePartSource",})
export const FilePart = Schema.Struct({ ...partBase, type: Schema.Literal("file"), mime: Schema.String, filename: Schema.optional(Schema.String), url: Schema.String, source: Schema.optional(FilePartSource),}).annotate({ identifier: "SessionV1.FilePart" })export type FilePart = Types.DeepMutable<Schema.Schema.Type<typeof FilePart>>
export const AgentPart = Schema.Struct({ ...partBase, type: Schema.Literal("agent"), name: Schema.String, source: Schema.optional( Schema.Struct({ value: Schema.String, start: NonNegativeInt, end: NonNegativeInt, }), ),}).annotate({ identifier: "SessionV1.AgentPart" })export type AgentPart = Types.DeepMutable<Schema.Schema.Type<typeof AgentPart>>
export const CompactionPart = Schema.Struct({ ...partBase, type: Schema.Literal("compaction"), auto: Schema.Boolean, overflow: Schema.optional(Schema.Boolean), tail_start_id: Schema.optional(MessageID),}).annotate({ identifier: "SessionV1.CompactionPart" })export type CompactionPart = Types.DeepMutable<Schema.Schema.Type<typeof CompactionPart>>
export const SubtaskPart = Schema.Struct({ ...partBase, type: Schema.Literal("subtask"), prompt: Schema.String, description: Schema.String, agent: Schema.String, model: Schema.optional( Schema.Struct({ providerID: Provider.ID, modelID: Model.ID, }), ), command: Schema.optional(Schema.String),}).annotate({ identifier: "SessionV1.SubtaskPart" })export type SubtaskPart = Types.DeepMutable<Schema.Schema.Type<typeof SubtaskPart>>
export const RetryPart = Schema.Struct({ ...partBase, type: Schema.Literal("retry"), attempt: NonNegativeInt, error: APIError.EffectSchema, time: Schema.Struct({ created: NonNegativeInt, }),}).annotate({ identifier: "SessionV1.RetryPart" })export type RetryPart = Omit<Types.DeepMutable<Schema.Schema.Type<typeof RetryPart>>, "error"> & { error: APIError}
export const StepStartPart = Schema.Struct({ ...partBase, type: Schema.Literal("step-start"), snapshot: Schema.optional(Schema.String),}).annotate({ identifier: "SessionV1.StepStartPart" })export type StepStartPart = Types.DeepMutable<Schema.Schema.Type<typeof StepStartPart>>
export const StepFinishPart = Schema.Struct({ ...partBase, type: Schema.Literal("step-finish"), reason: Schema.String, snapshot: Schema.optional(Schema.String), cost: Schema.Finite, tokens: Schema.Struct({ total: Schema.optional(Schema.Finite), input: Schema.Finite, output: Schema.Finite, reasoning: Schema.Finite, cache: Schema.Struct({ read: Schema.Finite, write: Schema.Finite, }), }),}).annotate({ identifier: "SessionV1.StepFinishPart" })export type StepFinishPart = Types.DeepMutable<Schema.Schema.Type<typeof StepFinishPart>>
export const ToolStatePending = Schema.Struct({ status: Schema.Literal("pending"), input: Schema.Record(Schema.String, Schema.Any), raw: Schema.String,}).annotate({ identifier: "SessionV1.ToolStatePending" })export type ToolStatePending = Types.DeepMutable<Schema.Schema.Type<typeof ToolStatePending>>
export const ToolStateRunning = Schema.Struct({ status: Schema.Literal("running"), input: Schema.Record(Schema.String, Schema.Any), title: Schema.optional(Schema.String), metadata: Schema.optional(Schema.Record(Schema.String, Schema.Any)), time: Schema.Struct({ start: NonNegativeInt, }),}).annotate({ identifier: "SessionV1.ToolStateRunning" })export type ToolStateRunning = Types.DeepMutable<Schema.Schema.Type<typeof ToolStateRunning>>
export const ToolStateCompleted = Schema.Struct({ status: Schema.Literal("completed"), input: Schema.Record(Schema.String, Schema.Any), output: Schema.String, title: Schema.String, metadata: Schema.Record(Schema.String, Schema.Any), time: Schema.Struct({ start: NonNegativeInt, end: NonNegativeInt, compacted: Schema.optional(NonNegativeInt), }), attachments: Schema.optional(Schema.Array(FilePart)),}).annotate({ identifier: "SessionV1.ToolStateCompleted" })export type ToolStateCompleted = Types.DeepMutable<Schema.Schema.Type<typeof ToolStateCompleted>>
export const ToolStateError = Schema.Struct({ status: Schema.Literal("error"), input: Schema.Record(Schema.String, Schema.Any), error: Schema.String, metadata: Schema.optional(Schema.Record(Schema.String, Schema.Any)), time: Schema.Struct({ start: NonNegativeInt, end: NonNegativeInt, }),}).annotate({ identifier: "SessionV1.ToolStateError" })export type ToolStateError = Types.DeepMutable<Schema.Schema.Type<typeof ToolStateError>>
export const ToolState = Schema.Union([ ToolStatePending, ToolStateRunning, ToolStateCompleted, ToolStateError,]).annotate({ discriminator: "status", identifier: "SessionV1.ToolState",})export type ToolState = ToolStatePending | ToolStateRunning | ToolStateCompleted | ToolStateError
export const ToolPart = Schema.Struct({ ...partBase, type: Schema.Literal("tool"), callID: Schema.String, tool: Schema.String, state: ToolState, metadata: Schema.optional(Schema.Record(Schema.String, Schema.Any)),}).annotate({ identifier: "SessionV1.ToolPart" })export type ToolPart = Omit<Types.DeepMutable<Schema.Schema.Type<typeof ToolPart>>, "state"> & { state: ToolState}
const messageBase = { id: MessageID, sessionID: partBase.sessionID,}
export const User = Schema.Struct({ ...messageBase, role: Schema.Literal("user"), time: Schema.Struct({ created: Timestamp, }), format: Schema.optional(Format), summary: Schema.optional( Schema.Struct({ title: Schema.optional(Schema.String), body: Schema.optional(Schema.String), diffs: Schema.Array(FileDiff.LegacyInfo), }), ), agent: Schema.String, model: Schema.Struct({ providerID: Provider.ID, modelID: Model.ID, variant: Schema.optional(Schema.String), }), system: Schema.optional(Schema.String), tools: Schema.optional(Schema.Record(Schema.String, Schema.Boolean)),}).annotate({ identifier: "SessionV1.UserMessage" })export type User = Types.DeepMutable<Schema.Schema.Type<typeof User>>
export const Part = Schema.Union([ TextPart, SubtaskPart, ReasoningPart, FilePart, ToolPart, StepStartPart, StepFinishPart, SnapshotPart, PatchPart, AgentPart, RetryPart, CompactionPart,]).annotate({ discriminator: "type", identifier: "SessionV1.Part" })export type Part = | TextPart | SubtaskPart | ReasoningPart | FilePart | ToolPart | StepStartPart | StepFinishPart | SnapshotPart | PatchPart | AgentPart | RetryPart | CompactionPart
const AssistantErrorSchema = Schema.Union([ AuthError.EffectSchema, namedError("UnknownError", { message: Schema.String, ref: Schema.optional(Schema.String) }).EffectSchema, OutputLengthError.EffectSchema, AbortedError.EffectSchema, StructuredOutputError.EffectSchema, ContextOverflowError.EffectSchema, ContentFilterError.EffectSchema, APIError.EffectSchema,]).annotate({ discriminator: "name" })type AssistantError = Schema.Schema.Type<typeof AssistantErrorSchema>
export const TextPartInput = Schema.Struct({ id: Schema.optional(PartID), type: Schema.Literal("text"), text: Schema.String, synthetic: Schema.optional(Schema.Boolean), ignored: Schema.optional(Schema.Boolean), time: Schema.optional( Schema.Struct({ start: NonNegativeInt, end: Schema.optional(NonNegativeInt), }), ), metadata: Schema.optional(Schema.Record(Schema.String, Schema.Any)),}).annotate({ identifier: "SessionV1.TextPartInput" })export type TextPartInput = Types.DeepMutable<Schema.Schema.Type<typeof TextPartInput>>
export const FilePartInput = Schema.Struct({ id: Schema.optional(PartID), type: Schema.Literal("file"), mime: Schema.String, filename: Schema.optional(Schema.String), url: Schema.String, source: Schema.optional(FilePartSource),}).annotate({ identifier: "SessionV1.FilePartInput" })export type FilePartInput = Types.DeepMutable<Schema.Schema.Type<typeof FilePartInput>>
export const AgentPartInput = Schema.Struct({ id: Schema.optional(PartID), type: Schema.Literal("agent"), name: Schema.String, source: Schema.optional( Schema.Struct({ value: Schema.String, start: NonNegativeInt, end: NonNegativeInt, }), ),}).annotate({ identifier: "SessionV1.AgentPartInput" })export type AgentPartInput = Types.DeepMutable<Schema.Schema.Type<typeof AgentPartInput>>
export const SubtaskPartInput = Schema.Struct({ id: Schema.optional(PartID), type: Schema.Literal("subtask"), prompt: Schema.String, description: Schema.String, agent: Schema.String, model: Schema.optional( Schema.Struct({ providerID: Provider.ID, modelID: Model.ID, }), ), command: Schema.optional(Schema.String),}).annotate({ identifier: "SessionV1.SubtaskPartInput" })export type SubtaskPartInput = Types.DeepMutable<Schema.Schema.Type<typeof SubtaskPartInput>>
export const Assistant = Schema.Struct({ ...messageBase, role: Schema.Literal("assistant"), time: Schema.Struct({ created: NonNegativeInt, completed: Schema.optional(NonNegativeInt), }), error: Schema.optional(AssistantErrorSchema), parentID: MessageID, modelID: Model.ID, providerID: Provider.ID, mode: Schema.String, agent: Schema.String, path: Schema.Struct({ cwd: Schema.String, root: Schema.String, }), summary: Schema.optional(Schema.Boolean), cost: Schema.Finite, tokens: Schema.Struct({ total: Schema.optional(Schema.Finite), input: Schema.Finite, output: Schema.Finite, reasoning: Schema.Finite, cache: Schema.Struct({ read: Schema.Finite, write: Schema.Finite, }), }), structured: Schema.optional(Schema.Any), variant: Schema.optional(Schema.String), finish: Schema.optional(Schema.String),}).annotate({ identifier: "SessionV1.AssistantMessage" })export type Assistant = Omit<Types.DeepMutable<Schema.Schema.Type<typeof Assistant>>, "error"> & { error?: AssistantError}
export const Info = Schema.Union([User, Assistant]).annotate({ discriminator: "role", identifier: "SessionV1.Message" })export type Info = User | Assistant
export const WithParts = Schema.Struct({ info: Info, parts: Schema.Array(Part),})export type WithParts = { info: Info parts: Part[]}
const options = { durable: { aggregate: "sessionID", version: 1, },} as const
const SessionSummary = Schema.Struct({ additions: Schema.Finite, deletions: Schema.Finite, files: Schema.Finite, diffs: optional(Schema.Array(FileDiff.LegacyInfo)),})
const SessionTokens = Schema.Struct({ input: Schema.Finite, output: Schema.Finite, reasoning: Schema.Finite, cache: Schema.Struct({ read: Schema.Finite, write: Schema.Finite, }),})
const SessionShare = Schema.Struct({ url: Schema.String,})
const SessionRevert = Schema.Struct({ messageID: MessageID, partID: optional(PartID), snapshot: optional(Schema.String), diff: optional(Schema.String),})
const SessionModel = Schema.Struct({ id: Model.ID, providerID: Provider.ID, variant: optional(Schema.String),})
export const SessionInfo = Schema.Struct({ id: SessionID, slug: Schema.String, projectID: Project.ID, workspaceID: optional(WorkspaceID), directory: Schema.String, path: optional(Schema.String), parentID: optional(SessionID), summary: optional(SessionSummary), cost: optional(Schema.Finite), tokens: optional(SessionTokens), share: optional(SessionShare), title: optional(Schema.String), agent: optional(Schema.String), model: optional(SessionModel), version: Schema.String, metadata: optional(Schema.Record(Schema.String, Schema.Any)), time: Schema.Struct({ created: NonNegativeInt, updated: NonNegativeInt, compacting: optional(NonNegativeInt), archived: optional(Schema.Finite), }), permission: optional(PermissionV1.Ruleset), revert: optional(SessionRevert),}).annotate({ identifier: "SessionV1.Info" })export type SessionInfo = typeof SessionInfo.Type
const events = { Created: durable({ type: "session.created", ...options, schema: { sessionID: SessionID, info: SessionInfo, }, }), Updated: durable({ type: "session.updated", ...options, schema: { sessionID: SessionID, info: SessionInfo, }, }), Deleted: durable({ type: "session.deleted", ...options, schema: { sessionID: SessionID, info: SessionInfo, }, }), MessageUpdated: durable({ type: "message.updated", ...options, schema: { sessionID: SessionID, info: Info, }, }), MessageRemoved: durable({ type: "message.removed", ...options, schema: { sessionID: SessionID, messageID: MessageID, }, }), PartUpdated: durable({ type: "message.part.updated", ...options, schema: { sessionID: SessionID, part: Part, time: Schema.Finite, }, }), PartRemoved: durable({ type: "message.part.removed", ...options, schema: { sessionID: SessionID, messageID: MessageID, partID: PartID, }, }),}
export const PartDelta = ephemeral({ type: "message.part.delta", schema: { sessionID: SessionID, messageID: MessageID, partID: PartID, field: Schema.String, delta: Schema.String, },})
export const Diff = ephemeral({ type: "session.diff", schema: { sessionID: SessionID, diff: Schema.Array(FileDiff.LegacyInfo), },})
export const Error = ephemeral({ type: "session.error", schema: { sessionID: Schema.optional(SessionID), error: Assistant.fields.error, },})
export const Event = { ...events, PartDelta, Diff, Error, Definitions: inventory( events.Created, events.Updated, events.Deleted, events.MessageUpdated, events.MessageRemoved, events.PartUpdated, events.PartRemoved, PartDelta, Diff, Error, ),}