feat: add experimental background subagents (#27084)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { Slug } from "@opencode-ai/core/util/slug"
|
||||
import path from "path"
|
||||
import { BackgroundJob } from "@/background/job"
|
||||
import { BusEvent } from "@/bus/bus-event"
|
||||
import { Bus } from "@/bus"
|
||||
import { Decimal } from "decimal.js"
|
||||
@@ -508,10 +509,11 @@ const db = <T>(fn: (d: Parameters<typeof Database.use>[0] extends (trx: infer D)
|
||||
export const layer: Layer.Layer<
|
||||
Service,
|
||||
never,
|
||||
Bus.Service | Storage.Service | SyncEvent.Service | RuntimeFlags.Service
|
||||
BackgroundJob.Service | Bus.Service | Storage.Service | SyncEvent.Service | RuntimeFlags.Service
|
||||
> = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const background = yield* BackgroundJob.Service
|
||||
const bus = yield* Bus.Service
|
||||
const storage = yield* Storage.Service
|
||||
const sync = yield* SyncEvent.Service
|
||||
@@ -592,20 +594,19 @@ export const layer: Layer.Layer<
|
||||
const remove: Interface["remove"] = Effect.fnUntraced(function* (sessionID: SessionID) {
|
||||
const session = yield* get(sessionID)
|
||||
try {
|
||||
const kids = yield* children(sessionID)
|
||||
for (const child of kids) {
|
||||
yield* remove(child.id)
|
||||
}
|
||||
|
||||
// `remove` needs to work in all cases, such as a broken
|
||||
// sessions that run cleanup. In certain cases these will
|
||||
// run without any instance state, so we need to turn off
|
||||
// publishing of events in that case
|
||||
// `remove` needs to work in all cases, such as broken sessions that
|
||||
// run cleanup without instance state.
|
||||
const hasInstance = yield* InstanceState.directory.pipe(
|
||||
Effect.as(true),
|
||||
Effect.catchCause(() => Effect.succeed(false)),
|
||||
)
|
||||
|
||||
if (hasInstance) yield* cancelBackgroundJobs(background, sessionID)
|
||||
const kids = yield* children(sessionID)
|
||||
for (const child of kids) {
|
||||
yield* remove(child.id)
|
||||
}
|
||||
|
||||
yield* sync.run(Event.Deleted, { sessionID, info: session }, { publish: hasInstance })
|
||||
yield* sync.remove(sessionID)
|
||||
} catch (e) {
|
||||
@@ -862,12 +863,30 @@ export const layer: Layer.Layer<
|
||||
)
|
||||
|
||||
export const defaultLayer = layer.pipe(
|
||||
Layer.provide(BackgroundJob.defaultLayer),
|
||||
Layer.provide(Bus.layer),
|
||||
Layer.provide(Storage.defaultLayer),
|
||||
Layer.provide(SyncEvent.defaultLayer),
|
||||
Layer.provide(RuntimeFlags.defaultLayer),
|
||||
)
|
||||
|
||||
const cancelBackgroundJobs = Effect.fn("Session.cancelBackgroundJobs")(function* (
|
||||
background: BackgroundJob.Interface,
|
||||
sessionID: SessionID,
|
||||
) {
|
||||
const jobs = yield* background.list()
|
||||
yield* Effect.forEach(
|
||||
jobs.filter((job) => {
|
||||
if (job.status !== "running") return false
|
||||
if (job.id === sessionID) return true
|
||||
if (job.metadata?.sessionId === sessionID) return true
|
||||
return job.metadata?.parentSessionId === sessionID
|
||||
}),
|
||||
(job) => background.cancel(job.id),
|
||||
{ concurrency: "unbounded", discard: true },
|
||||
)
|
||||
})
|
||||
|
||||
function* listByProject(
|
||||
input: ListInput & {
|
||||
projectID: ProjectID
|
||||
|
||||
Reference in New Issue
Block a user