feat(session): expose transient generation API (#37433)

This commit is contained in:
Kit Langton 2026-07-17 09:25:50 -04:00 committed by GitHub
commit 3db4458e6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 157 additions and 39 deletions

View file

@ -424,6 +424,7 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Int
}),
get: (input) => runtime.session.get(input.sessionID),
prompt: runtime.session.prompt,
generate: (input) => runtime.session.generate(input).pipe(Effect.map((text) => ({ text }))),
command: runtime.session.command,
synthetic: runtime.session.synthetic,
interrupt: (input) => runtime.session.interrupt(input.sessionID),

View file

@ -231,6 +231,8 @@ export function fromPromise(plugin: Plugin) {
resume: input.resume ?? undefined,
}),
),
generate: (input) =>
run(host.session.generate({ sessionID: Session.ID.make(input.sessionID), prompt: input.prompt })),
command: (input) =>
run(
host.session.command({

View file

@ -11,7 +11,7 @@ import { SessionV2 } from "../session"
export interface Interface {
readonly session: Pick<
SessionV2.Interface,
"get" | "create" | "messages" | "prompt" | "command" | "resume" | "interrupt" | "synthetic"
"get" | "create" | "messages" | "prompt" | "generate" | "command" | "resume" | "interrupt" | "synthetic"
>
readonly job: Pick<Job.Interface, "start" | "wait" | "block" | "background" | "cancel">
readonly location: {
@ -50,6 +50,7 @@ export const layerWithCell = (cell: Cell) =>
create: (input) => require(cell, (runtime) => runtime.session.create(input)),
messages: (input) => require(cell, (runtime) => runtime.session.messages(input)),
prompt: (input) => require(cell, (runtime) => runtime.session.prompt(input)),
generate: (input) => require(cell, (runtime) => runtime.session.generate(input)),
command: (input) => require(cell, (runtime) => runtime.session.command(input)),
resume: (sessionID) => require(cell, (runtime) => runtime.session.resume(sessionID)),
interrupt: (sessionID) => require(cell, (runtime) => runtime.session.interrupt(sessionID)),

View file

@ -96,6 +96,7 @@ export function host(overrides: Overrides = {}): PluginContext {
create: overrides.session?.create ?? (() => Effect.die("unused session.create")),
get: overrides.session?.get ?? (() => Effect.die("unused session.get")),
prompt: overrides.session?.prompt ?? (() => Effect.die("unused session.prompt")),
generate: overrides.session?.generate ?? (() => Effect.die("unused session.generate")),
command: overrides.session?.command ?? (() => Effect.die("unused session.command")),
synthetic: overrides.session?.synthetic ?? (() => Effect.die("unused session.synthetic")),
interrupt: overrides.session?.interrupt ?? (() => Effect.die("unused session.interrupt")),

View file

@ -24,6 +24,27 @@ import { host as testHost } from "./host"
const it = testEffect(PluginTestLayer)
describe("fromPromise", () => {
it.effect("forwards transient session generation", () =>
Effect.gen(function* () {
const host = testHost({
session: {
generate: (input) => Effect.succeed({ text: `${input.sessionID}: ${input.prompt}` }),
},
})
yield* PluginPromise.fromPromise(
Plugin.define({
id: "promise-session-generate",
setup: async (ctx) => {
expect(await ctx.session.generate({ sessionID: "ses_generate", prompt: "Summarize" })).toEqual({
text: "ses_generate: Summarize",
})
},
}),
).effect(host)
}),
)
it.effect("forwards synthetic session input", () =>
Effect.gen(function* () {
const input = {