use forkScoped + Fiber.join for lazy init (match old Instance.state behavior)

kit/effectify-command-review
Kit Langton 2026-03-19 16:01:48 -04:00
parent df260fee45
commit 59cc1ebc27
1 changed files with 167 additions and 1 deletions

View File

@ -2,7 +2,7 @@ import { BusEvent } from "@/bus/bus-event"
import { InstanceState } from "@/effect/instance-state"
import { makeRunPromise } from "@/effect/run-service"
import { SessionID, MessageID } from "@/session/schema"
import { Effect, Layer, ServiceMap } from "effect"
import { Effect, Fiber, Layer, ServiceMap } from "effect"
import z from "zod"
import { Config } from "../config/config"
import PROMPT_INITIALIZE from "./template/initialize.txt"
@ -78,9 +78,17 @@ export namespace Command {
const commands: Record<string, Info> = {}
let task: Promise<void> | undefined
<<<<<<< HEAD
async function load() {
const cfg = await Config.get()
||||||| parent of 8e11a46fe (use forkScoped + Fiber.join for lazy init (match old Instance.state behavior))
const commands = yield* Effect.promise(async () => {
const cfg = await Config.get()
=======
const commands: Record<string, Info> = {}
>>>>>>> 8e11a46fe (use forkScoped + Fiber.join for lazy init (match old Instance.state behavior))
<<<<<<< HEAD
commands[Default.INIT] = {
name: Default.INIT,
description: "create/update AGENTS.md",
@ -153,8 +161,68 @@ export namespace Command {
hints: [],
}
}
||||||| parent of 8e11a46fe (use forkScoped + Fiber.join for lazy init (match old Instance.state behavior))
const result: Record<string, Info> = {
[Default.INIT]: {
name: Default.INIT,
description: "create/update AGENTS.md",
source: "command",
get template() {
return PROMPT_INITIALIZE.replace("${path}", instance.worktree)
},
hints: hints(PROMPT_INITIALIZE),
},
[Default.REVIEW]: {
name: Default.REVIEW,
description: "review changes [commit|branch|pr], defaults to uncommitted",
source: "command",
get template() {
return PROMPT_REVIEW.replace("${path}", instance.worktree)
},
subtask: true,
hints: hints(PROMPT_REVIEW),
},
}
for (const [name, command] of Object.entries(cfg.command ?? {})) {
result[name] = {
name,
agent: command.agent,
model: command.model,
description: command.description,
source: "command",
get template() {
return command.template
},
subtask: command.subtask,
hints: hints(command.template),
=======
const load = Effect.fn("Command.load")(function* () {
yield* Effect.promise(async () => {
const cfg = await Config.get()
commands[Default.INIT] = {
name: Default.INIT,
description: "create/update AGENTS.md",
source: "command",
get template() {
return PROMPT_INITIALIZE.replace("${path}", instance.worktree)
},
hints: hints(PROMPT_INITIALIZE),
}
commands[Default.REVIEW] = {
name: Default.REVIEW,
description: "review changes [commit|branch|pr], defaults to uncommitted",
source: "command",
get template() {
return PROMPT_REVIEW.replace("${path}", instance.worktree)
},
subtask: true,
hints: hints(PROMPT_REVIEW),
>>>>>>> 8e11a46fe (use forkScoped + Fiber.join for lazy init (match old Instance.state behavior))
}
<<<<<<< HEAD
return {
commands,
ensure: () => {
@ -166,20 +234,118 @@ export namespace Command {
)
return task
},
||||||| parent of 8e11a46fe (use forkScoped + Fiber.join for lazy init (match old Instance.state behavior))
// Add skills as invokable commands
for (const skill of await Skill.all()) {
// Skip if a command with this name already exists
if (result[skill.name]) continue
result[skill.name] = {
name: skill.name,
description: skill.description,
source: "skill",
get template() {
return skill.content
},
hints: [],
=======
for (const [name, command] of Object.entries(cfg.command ?? {})) {
commands[name] = {
name,
agent: command.agent,
model: command.model,
description: command.description,
source: "command",
get template() {
return command.template
},
subtask: command.subtask,
hints: hints(command.template),
}
}
for (const [name, prompt] of Object.entries(await MCP.prompts())) {
commands[name] = {
name,
source: "mcp",
description: prompt.description,
get template() {
// since a getter can't be async we need to manually return a promise here
return new Promise<string>(async (resolve, reject) => {
const template = await MCP.getPrompt(
prompt.client,
prompt.name,
prompt.arguments
? // substitute each argument with $1, $2, etc.
Object.fromEntries(prompt.arguments?.map((argument, i) => [argument.name, `$${i + 1}`]))
: {},
).catch(reject)
resolve(
template?.messages
.map((message) => (message.content.type === "text" ? message.content.text : ""))
.join("\n") || "",
)
})
},
hints: prompt.arguments?.map((_, i) => `$${i + 1}`) ?? [],
}
>>>>>>> 8e11a46fe (use forkScoped + Fiber.join for lazy init (match old Instance.state behavior))
}
<<<<<<< HEAD
}),
)
||||||| parent of 8e11a46fe (use forkScoped + Fiber.join for lazy init (match old Instance.state behavior))
}
return result
})
=======
// Add skills as invokable commands
for (const skill of await Skill.all()) {
// Skip if a command with this name already exists
if (commands[skill.name]) continue
commands[skill.name] = {
name: skill.name,
description: skill.description,
source: "skill",
get template() {
return skill.content
},
hints: [],
}
}
})
})
>>>>>>> 8e11a46fe (use forkScoped + Fiber.join for lazy init (match old Instance.state behavior))
const loadFiber = yield* load().pipe(
Effect.catchCause(() => Effect.void),
Effect.forkScoped,
)
const get = Effect.fn("Command.get")(function* (name: string) {
<<<<<<< HEAD
const state = yield* InstanceState.get(cache)
yield* Effect.promise(() => state.ensure())
return state.commands[name]
||||||| parent of 8e11a46fe (use forkScoped + Fiber.join for lazy init (match old Instance.state behavior))
return commands[name]
=======
yield* Fiber.join(loadFiber)
return commands[name]
>>>>>>> 8e11a46fe (use forkScoped + Fiber.join for lazy init (match old Instance.state behavior))
})
const list = Effect.fn("Command.list")(function* () {
<<<<<<< HEAD
const state = yield* InstanceState.get(cache)
yield* Effect.promise(() => state.ensure())
return Object.values(state.commands)
||||||| parent of 8e11a46fe (use forkScoped + Fiber.join for lazy init (match old Instance.state behavior))
return Object.values(commands)
=======
yield* Fiber.join(loadFiber)
return Object.values(commands)
>>>>>>> 8e11a46fe (use forkScoped + Fiber.join for lazy init (match old Instance.state behavior))
})
return Service.of({ get, list })