ignore: exploration

This commit is contained in:
Dax Raad
2026-04-12 13:14:33 -04:00
parent 8b9b9ad31e
commit 2aa6110c6e
2 changed files with 145 additions and 27 deletions

View File

@@ -10,59 +10,106 @@ export namespace Message {
})),
)
export class File extends Schema.Class<File>("Message.File")({
url: Schema.String,
export class Source extends Schema.Class<Source>("Message.Source")({
start: Schema.Number,
end: Schema.Number,
text: Schema.String,
}) {}
export class FileAttachment extends Schema.Class<FileAttachment>("Message.File.Attachment")({
uri: Schema.String,
mime: Schema.String,
name: Schema.String.pipe(Schema.optional),
description: Schema.String.pipe(Schema.optional),
source: Source.pipe(Schema.optional),
}) {
static create(url: string) {
return new File({
url,
return new FileAttachment({
uri: url,
mime: "text/plain",
})
}
}
export class UserContent extends Schema.Class<UserContent>("Message.User.Content")({
text: Schema.String,
synthetic: Schema.Boolean.pipe(Schema.optional),
agent: Schema.String.pipe(Schema.optional),
files: Schema.Array(File).pipe(Schema.optional),
export class AgentAttachment extends Schema.Class<AgentAttachment>("Message.Agent.Attachment")({
name: Schema.String,
source: Source.pipe(Schema.optional),
}) {}
export class User extends Schema.Class<User>("Message.User")({
id: ID,
type: Schema.Literal("user"),
text: Schema.String,
files: Schema.Array(FileAttachment).pipe(Schema.optional),
agents: Schema.Array(AgentAttachment).pipe(Schema.optional),
time: Schema.Struct({
created: Schema.DateTimeUtc,
}),
content: UserContent,
}) {
static create(content: Schema.Schema.Type<typeof UserContent>) {
static create(input: { text: User["text"]; files?: User["files"]; agents?: User["agents"] }) {
const msg = new User({
id: ID.create(),
type: "user",
...input,
time: {
created: Effect.runSync(DateTime.now),
},
content,
})
return msg
}
static file(url: string) {
return new File({
url,
mime: "text/plain",
})
}
}
export namespace User {}
export class Synthetic extends Schema.Class<Synthetic>("Message.Synthetic")({
id: ID,
type: Schema.Literal("synthetic"),
text: Schema.String,
time: Schema.Struct({
created: Schema.DateTimeUtc,
}),
}) {}
export class Request extends Schema.Class<Request>("Message.Request")({
id: ID,
type: Schema.Literal("start"),
model: Schema.Struct({
id: Schema.String,
providerID: Schema.String,
variant: Schema.String.pipe(Schema.optional),
}),
time: Schema.Struct({
created: Schema.DateTimeUtc,
}),
}) {}
export class Text extends Schema.Class<Text>("Message.Text")({
id: ID,
type: Schema.Literal("text"),
text: Schema.String,
time: Schema.Struct({
created: Schema.DateTimeUtc,
completed: Schema.DateTimeUtc.pipe(Schema.optional),
}),
}) {}
export class Complete extends Schema.Class<Complete>("Message.Complete")({
id: ID,
type: Schema.Literal("complete"),
time: Schema.Struct({
created: Schema.DateTimeUtc,
}),
cost: Schema.Number,
tokens: Schema.Struct({
total: Schema.Number,
input: Schema.Number,
output: Schema.Number,
reasoning: Schema.Number,
cache: Schema.Struct({
read: Schema.Number,
write: Schema.Number,
}),
}),
}) {}
export const Info = Schema.Union([User, Text])
export type Info = Schema.Schema.Type<typeof Info>
}
const msg = Message.User.create({
text: "Hello world",
files: [Message.File.create("file://example.com/file.txt")],
})
console.log(JSON.stringify(msg, null, 2))

View File

@@ -0,0 +1,71 @@
import { Context, Layer, Schema, Effect } from "effect"
import { Message } from "./message"
import { Struct } from "effect"
import { Identifier } from "@/id/id"
import { withStatics } from "@/util/schema"
import { Session } from "@/session"
import { SessionID } from "@/session/schema"
export namespace SessionV2 {
export const ID = SessionID
export type ID = Schema.Schema.Type<typeof ID>
export class PromptInput extends Schema.Class<PromptInput>("Session.PromptInput")({
...Struct.omit(Message.User.fields, ["time", "type"]),
id: Schema.optionalKey(Message.ID),
sessionID: SessionV2.ID,
}) {}
export class CreateInput extends Schema.Class<CreateInput>("Session.CreateInput")({
id: Schema.optionalKey(SessionV2.ID),
}) {}
export class Info extends Schema.Class<Info>("Session.Info")({
id: SessionV2.ID,
model: Schema.Struct({
id: Schema.String,
providerID: Schema.String,
modelID: Schema.String,
}).pipe(Schema.optional),
}) {}
export interface Interface {
fromID: (id: SessionV2.ID) => Effect.Effect<Info>
create: (input: CreateInput) => Effect.Effect<Info>
prompt: (input: PromptInput) => Effect.Effect<Message.User>
}
export class Service extends Context.Service<Service, Interface>()("Session.Service") {}
export const layer = Layer.effect(Service)(
Effect.gen(function* () {
const session = yield* Session.Service
const create: Interface["create"] = Effect.fn("Session.create")(function* (input) {
throw new Error("Not implemented")
})
const prompt: Interface["prompt"] = Effect.fn("Session.prompt")(function* (input) {
throw new Error("Not implemented")
})
const fromID: Interface["fromID"] = Effect.fn("Session.fromID")(function* (id) {
const match = yield* session.get(id)
return fromV1(match)
})
return Service.of({
create,
prompt,
fromID,
})
}),
)
function fromV1(input: Session.Info): Info {
return new Info({
id: SessionV2.ID.make(input.id),
})
}
}