feat(core): add command registry (#30624)

This commit is contained in:
Dax
2026-06-04 02:57:43 -04:00
committed by GitHub
parent 70bb710715
commit 1ff19103a2
150 changed files with 4753 additions and 2657 deletions
+3 -2
View File
@@ -21,6 +21,7 @@ import { RuntimeFlags } from "@/effect/runtime-flags"
import { EventV2Bridge } from "@/event-v2-bridge"
import { SessionEvent } from "@opencode-ai/core/session/event"
import { ProviderV2 } from "@opencode-ai/core/provider"
import { ModelV2 } from "@opencode-ai/core/model"
import { EventV2 } from "@opencode-ai/core/event"
const log = Log.create({ service: "session.compaction" })
@@ -201,7 +202,7 @@ export interface Interface {
readonly create: (input: {
sessionID: SessionID
agent: string
model: { providerID: ProviderV2.ID; modelID: ProviderV2.ModelID }
model: { providerID: ProviderV2.ID; modelID: ModelV2.ID }
auto: boolean
overflow?: boolean
}) => Effect.Effect<void>
@@ -585,7 +586,7 @@ export const layer = Layer.effect(
const create = Effect.fn("SessionCompaction.create")(function* (input: {
sessionID: SessionID
agent: string
model: { providerID: ProviderV2.ID; modelID: ProviderV2.ModelID }
model: { providerID: ProviderV2.ID; modelID: ModelV2.ID }
auto: boolean
overflow?: boolean
}) {
+2 -1
View File
@@ -5,6 +5,7 @@ import { NonNegativeInt } from "@opencode-ai/core/schema"
import { MessageError } from "./message-error"
import { AuthError, OutputLengthError } from "./message-error"
import { ProviderV2 } from "@opencode-ai/core/provider"
import { ModelV2 } from "@opencode-ai/core/model"
export { AuthError, OutputLengthError } from "./message-error"
export const ToolCall = Schema.Struct({
@@ -120,7 +121,7 @@ export const Info = Schema.Struct({
assistant: Schema.optional(
Schema.Struct({
system: Schema.Array(Schema.String),
modelID: ProviderV2.ModelID,
modelID: ModelV2.ID,
providerID: ProviderV2.ID,
path: Schema.Struct({
cwd: Schema.String,
+4 -4
View File
@@ -241,7 +241,7 @@ export const layer = Layer.effect(
session: Session.Info
history: SessionV1.WithParts[]
providerID: ProviderV2.ID
modelID: ProviderV2.ModelID
modelID: ModelV2.ID
}) {
if (input.session.parentID) return
if (!Session.isDefaultTitle(input.session.title)) return
@@ -653,7 +653,7 @@ export const layer = Layer.effect(
const getModel = Effect.fn("SessionPrompt.getModel")(function* (
providerID: ProviderV2.ID,
modelID: ProviderV2.ModelID,
modelID: ModelV2.ID,
sessionID: SessionID,
) {
const exit = yield* provider.getModel(providerID, modelID).pipe(Effect.exit)
@@ -681,7 +681,7 @@ export const layer = Layer.effect(
if (current?.model) {
return {
providerID: ProviderV2.ID.make(current.model.providerID),
modelID: ProviderV2.ModelID.make(current.model.id),
modelID: ModelV2.ID.make(current.model.id),
...(current.model.variant && current.model.variant !== "default" ? { variant: current.model.variant } : {}),
}
}
@@ -1679,7 +1679,7 @@ export const defaultLayer = Layer.suspend(() =>
)
const ModelRef = Schema.Struct({
providerID: ProviderV2.ID,
modelID: ProviderV2.ModelID,
modelID: ModelV2.ID,
})
export const PromptInput = Schema.Struct({
+6 -35
View File
@@ -40,9 +40,10 @@ import type { Provider } from "@/provider/provider"
import { Permission } from "@/permission"
import { Global } from "@opencode-ai/core/global"
import { Effect, Layer, Option, Context, Schema, Types } from "effect"
import { AbsolutePath, NonNegativeInt, optionalOmitUndefined } from "@opencode-ai/core/schema"
import { NonNegativeInt, optionalOmitUndefined } from "@opencode-ai/core/schema"
import { RuntimeFlags } from "@/effect/runtime-flags"
import { ProviderV2 } from "@opencode-ai/core/provider"
import { ModelV2 } from "@opencode-ai/core/model"
const log = Log.create({ service: "session" })
const runtime = makeRuntime(Database.Service, Database.defaultLayer)
@@ -82,7 +83,7 @@ export function fromRow(row: SessionRow): Info {
agent: row.agent ?? undefined,
model: row.model
? {
id: ProviderV2.ModelID.make(row.model.id),
id: ModelV2.ID.make(row.model.id),
providerID: ProviderV2.ID.make(row.model.providerID),
variant: row.model.variant,
}
@@ -112,13 +113,6 @@ export function fromRow(row: SessionRow): Info {
}
}
function eventLocation(info: Pick<Info, "directory" | "workspaceID">) {
return {
directory: AbsolutePath.make(info.directory),
workspaceID: info.workspaceID,
}
}
export function toRow(info: Info) {
return {
id: info.id,
@@ -209,7 +203,7 @@ const Revert = Schema.Struct({
})
const Model = Schema.Struct({
id: ProviderV2.ModelID,
id: ModelV2.ID,
providerID: ProviderV2.ID,
variant: optionalOmitUndefined(Schema.String),
})
@@ -544,20 +538,6 @@ export const layer: Layer.Layer<
const events = yield* EventV2Bridge.Service
const flags = yield* RuntimeFlags.Service
const locationForSession = Effect.fnUntraced(function* (sessionID: SessionID) {
const row = yield* db
.select({ directory: SessionTable.directory, workspaceID: SessionTable.workspace_id })
.from(SessionTable)
.where(eq(SessionTable.id, sessionID))
.get()
.pipe(Effect.orDie)
if (!row) return
return {
directory: AbsolutePath.make(row.directory),
workspaceID: row.workspaceID ?? undefined,
}
})
const createNext = Effect.fn("Session.createNext")(function* (input: {
id?: SessionID
title?: string
@@ -597,7 +577,6 @@ export const layer: Layer.Layer<
yield* events.publish(
SessionV1.Event.Created,
{ sessionID: result.id, info: result },
{ location: eventLocation(result) },
)
return result
@@ -688,7 +667,6 @@ export const layer: Layer.Layer<
yield* events.publish(
SessionV1.Event.Deleted,
{ sessionID, info: session },
{ location: eventLocation(session) },
)
yield* events.remove(sessionID)
} catch (e) {
@@ -698,14 +676,12 @@ export const layer: Layer.Layer<
const updateMessage = <T extends SessionV1.Info>(msg: T): Effect.Effect<T> =>
Effect.gen(function* () {
const location = yield* locationForSession(msg.sessionID)
yield* events.publish(SessionV1.Event.MessageUpdated, { sessionID: msg.sessionID, info: msg }, { location })
yield* events.publish(SessionV1.Event.MessageUpdated, { sessionID: msg.sessionID, info: msg })
return msg
}).pipe(Effect.withSpan("Session.updateMessage"))
const updatePart = <T extends SessionV1.Part>(part: T): Effect.Effect<T> =>
Effect.gen(function* () {
const location = yield* locationForSession(part.sessionID)
yield* events.publish(
SessionV1.Event.PartUpdated,
{
@@ -713,7 +689,6 @@ export const layer: Layer.Layer<
part: structuredClone(part),
time: Date.now(),
},
{ location },
)
return part
}).pipe(Effect.withSpan("Session.updatePart"))
@@ -819,7 +794,7 @@ export const layer: Layer.Layer<
revert: info.revert === null ? undefined : (info.revert ?? current.revert),
permission: info.permission === null ? undefined : (info.permission ?? current.permission),
} as Info
yield* events.publish(SessionV1.Event.Updated, { sessionID, info: next }, { location: eventLocation(next) })
yield* events.publish(SessionV1.Event.Updated, { sessionID, info: next })
})
const touch = Effect.fn("Session.touch")(function* (sessionID: SessionID) {
@@ -917,14 +892,12 @@ export const layer: Layer.Layer<
sessionID: SessionID
messageID: MessageID
}) {
const location = yield* locationForSession(input.sessionID)
yield* events.publish(
SessionV1.Event.MessageRemoved,
{
sessionID: input.sessionID,
messageID: input.messageID,
},
{ location },
)
return input.messageID
})
@@ -934,7 +907,6 @@ export const layer: Layer.Layer<
messageID: MessageID
partID: PartID
}) {
const location = yield* locationForSession(input.sessionID)
yield* events.publish(
SessionV1.Event.PartRemoved,
{
@@ -942,7 +914,6 @@ export const layer: Layer.Layer<
messageID: input.messageID,
partID: input.partID,
},
{ location },
)
return input.partID
})
+2 -1
View File
@@ -20,6 +20,7 @@ import { PartID } from "./schema"
import { Log } from "@opencode-ai/core/util/log"
import { EffectBridge } from "@/effect/bridge"
import { ProviderV2 } from "@opencode-ai/core/provider"
import { ModelV2 } from "@opencode-ai/core/model"
const log = Log.create({ service: "session.tools" })
@@ -75,7 +76,7 @@ export const resolve = Effect.fn("SessionTools.resolve")(function* (input: {
})
for (const item of yield* registry.tools({
modelID: ProviderV2.ModelID.make(input.model.api.id),
modelID: ModelV2.ID.make(input.model.api.id),
providerID: input.model.providerID,
agent: input.agent,
})) {