Skip to content

Instantly share code, notes, and snippets.

@jlongster
Last active July 17, 2026 14:50
Show Gist options
  • Select an option

  • Save jlongster/ff3fba95ba816b53b9115eb0b021b025 to your computer and use it in GitHub Desktop.

Select an option

Save jlongster/ff3fba95ba816b53b9115eb0b021b025 to your computer and use it in GitHub Desktop.
Minimal inline OpenCode SDK session integration
import "./env.js";
import { AbsolutePath, Model, Provider } from "@opencode-ai/sdk-next";
import { Cause, Deferred, Effect, Stream } from "effect";
import { startCli } from "./cli.js";
import { createInlineOpenCode } from "./inline-opencode.js";
const location = { directory: AbsolutePath.make(process.env.QBOT_LOCATION?.trim() || process.cwd()) };
const modelName = process.env.QBOT_MODEL?.trim() || "openai/gpt-5.6-terra";
const timeoutSeconds = Number(process.env.QBOT_TIMEOUT_SECONDS ?? "600");
const timeoutMs = (Number.isFinite(timeoutSeconds) && timeoutSeconds > 0 ? timeoutSeconds : 600) * 1000;
const model = parseModel(modelName);
async function run<A, E>(effect: Effect.Effect<A, E, never>) {
const exit = await Effect.runPromiseExit(effect);
if (exit._tag === "Success") return exit.value;
throw new Error(Cause.pretty(exit.cause));
}
const program = Effect.scoped(Effect.gen(function* () {
const opencode = yield* createInlineOpenCode;
yield* opencode.model.default({ location }).pipe(Effect.ignore);
const integration = yield* opencode.integration.get({ integrationID: "openai" as any, location });
if ((integration.data?.connections.length ?? 0) === 0) {
return yield* Effect.fail(new Error("No inline OpenAI ChatGPT credential is connected. Run `bun run auth` and connect ChatGPT first."));
}
const session = yield* opencode.sessions.create({ model, location });
const connected = yield* Deferred.make<void>();
let output: { onChunk: (chunk: string) => void; parts: Map<string, string> } | undefined;
yield* opencode.events.subscribe().pipe(
Stream.runForEach((event) => {
if (event.type === "server.connected") return Deferred.succeed(connected, undefined);
if (event.type !== "session.text.delta" && event.type !== "session.text.ended") return Effect.void;
if (event.data.sessionID !== session.id || !output) return Effect.void;
return Effect.sync(() => {
if (!output) return;
const key = `${event.data.assistantMessageID}:${event.data.textID}`;
const previous = output.parts.get(key) ?? "";
const next = event.type === "session.text.delta" ? previous + event.data.delta : event.data.text;
const chunk = event.type === "session.text.delta" ? event.data.delta : next.slice(previous.length);
output.parts.set(key, next);
if (chunk) output.onChunk(chunk);
});
}),
Effect.forkScoped,
);
yield* Deferred.await(connected);
yield* Effect.promise(() => startCli({
intro: `qbot ready inline (${modelName}).`,
ask: (text, onChunk) => {
output = { onChunk, parts: new Map() };
return run(Effect.gen(function* () {
yield* opencode.sessions.prompt({ sessionID: session.id, prompt: { text }, delivery: "steer" });
yield* opencode.sessions.wait({ sessionID: session.id }).pipe(Effect.timeout(timeoutMs));
const context = yield* opencode.sessions.context({ sessionID: session.id });
const assistant = context.findLast((message) => message.type === "assistant");
return assistant?.content.filter((part) => part.type === "text").map((part) => part.text).join("").trim() ?? "";
})).finally(() => output = undefined);
},
}));
}));
Effect.runPromiseExit(program).then((exit) => {
if (exit._tag === "Success") return;
console.error(Cause.pretty(exit.cause));
process.exitCode = 1;
});
function parseModel(value: string) {
const [providerID, ...modelParts] = value.split("/");
const [id, variant] = modelParts.join("/").split("#", 2);
if (!providerID || !id) throw new Error("QBOT_MODEL must be provider/model, for example openai/gpt-5.6-terra");
return {
providerID: Provider.ID.make(providerID),
id: Model.ID.make(id),
...(variant ? { variant: Model.VariantID.make(variant) } : {}),
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment