feat(plugin): expose app metadata (#38179)

This commit is contained in:
Dax 2026-07-21 18:16:25 -04:00 committed by GitHub
commit 8de40be6ea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
71 changed files with 477 additions and 286 deletions

View file

@ -10,7 +10,7 @@ import { llmClient } from "../effect/app-node-platform"
import { SessionEvent } from "./event"
import type { SessionMessage } from "./message"
import { SessionModelHeaders } from "./model-headers"
import { Client } from "@opencode-ai/util/client"
import { App } from "../app"
import { SessionRunnerModel } from "./runner/model"
import { SessionSchema } from "./schema"
import { toSessionError } from "./to-session-error"
@ -61,7 +61,7 @@ type Settings = {
}
type Dependencies = {
readonly client: string
readonly app: App.Info
readonly events: EventV2.Interface
readonly llm: {
readonly stream: (request: LLMRequest) => Stream.Stream<LLMEvent, LLMError>
@ -260,7 +260,7 @@ const make = (dependencies: Dependencies) => {
.stream(
LLM.request({
model: plan.model,
http: { headers: SessionModelHeaders.make(plan.session, dependencies.client) },
http: { headers: SessionModelHeaders.make(plan.session, dependencies.app) },
messages: [Message.user(plan.prompt)],
tools: [],
}),
@ -399,13 +399,13 @@ export const layer = Layer.effect(
const llm = yield* LLMClient.Service
const config = yield* Config.Service
const models = yield* SessionRunnerModel.Service
const client = yield* Client.Name
return make({ events, llm, models, config: settings(yield* config.entries()), client })
const app = yield* App.Metadata
return make({ events, llm, models, config: settings(yield* config.entries()), app })
}),
)
export const node = makeLocationNode({
service: Service,
layer,
deps: [EventV2.node, llmClient, Config.node, SessionRunnerModel.node, Client.node],
deps: [EventV2.node, llmClient, Config.node, SessionRunnerModel.node, App.node],
})

View file

@ -4,7 +4,7 @@ import { LLM, LLMClient, Message, SystemPart } from "@opencode-ai/ai"
import { Effect, Layer } from "effect"
import { Database } from "../database/database"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Client } from "@opencode-ai/util/client"
import { App } from "../app"
import { llmClient } from "../effect/app-node-platform"
import { PluginHooks } from "../plugin/hooks"
import { SessionContext } from "./context"
@ -23,7 +23,7 @@ export const layer = Layer.effect(
const hooks = yield* PluginHooks.Service
const llm = yield* LLMClient.Service
const models = yield* SessionRunnerModel.Service
const client = yield* Client.Name
const app = yield* App.Metadata
return SessionGenerate.Service.of({
generate: Effect.fn("SessionGenerate.generate")(function* (input) {
@ -51,7 +51,7 @@ export const layer = Layer.effect(
return (yield* llm.generate(
LLM.request({
model: model.model,
http: { headers: SessionModelHeaders.make(selection.session, client) },
http: { headers: SessionModelHeaders.make(selection.session, app) },
providerOptions: { openai: { promptCacheKey } },
system: contextEvent.system,
messages: contextEvent.messages,
@ -67,5 +67,5 @@ export const layer = Layer.effect(
export const node = makeLocationNode({
service: SessionGenerate.Service,
layer,
deps: [SessionContext.node, Database.node, PluginHooks.node, SessionRunnerModel.node, Client.node, llmClient],
deps: [SessionContext.node, Database.node, PluginHooks.node, SessionRunnerModel.node, App.node, llmClient],
})

View file

@ -1,14 +1,14 @@
export * as SessionModelHeaders from "./model-headers"
import { InstallationVersion } from "@opencode-ai/util/installation/version"
import { App } from "../app"
import { SessionSchema } from "./schema"
export const make = (session: Pick<SessionSchema.Info, "id" | "parentID" | "projectID">, client: string) => ({
export const make = (session: Pick<SessionSchema.Info, "id" | "parentID" | "projectID">, app: App.Info) => ({
"x-session-affinity": session.id,
"X-Session-Id": session.id,
...(session.parentID ? { "x-parent-session-id": session.parentID } : {}),
"User-Agent": `opencode/${InstallationVersion}`,
"User-Agent": App.useragent(app),
"x-opencode-project": session.projectID,
"x-opencode-session": session.id,
"x-opencode-client": client,
"x-opencode-client": app.name,
})

View file

@ -4,7 +4,7 @@ import { LLM, Message, SystemPart, type LLMRequest, type ToolContent } from "@op
import { SessionError } from "@opencode-ai/schema/session-error"
import { Context, Effect, Layer } from "effect"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Client } from "@opencode-ai/util/client"
import { App } from "../app"
import { ModelV2 } from "../model"
import { PluginHooks } from "../plugin/hooks"
import { ToolRegistry } from "../tool/registry"
@ -85,7 +85,7 @@ export const layer = Layer.effect(
Effect.gen(function* () {
const hooks = yield* PluginHooks.Service
const registry = yield* ToolRegistry.Service
const client = yield* Client.Name
const app = yield* App.Metadata
const prepare = Effect.fn("SessionModelRequest.prepare")(function* (input: PrepareInput) {
const session = input.context.session
@ -123,7 +123,7 @@ export const layer = Layer.effect(
const request = LLM.request({
model,
http: {
headers: SessionModelHeaders.make(session, client),
headers: SessionModelHeaders.make(session, app),
},
providerOptions: { openai: { promptCacheKey } },
system: contextEvent.system,
@ -157,5 +157,5 @@ export const layer = Layer.effect(
export const node = makeLocationNode({
service: Service,
layer,
deps: [PluginHooks.node, ToolRegistry.node, Client.node],
deps: [PluginHooks.node, ToolRegistry.node, App.node],
})

View file

@ -6,7 +6,7 @@ import { AgentV2 } from "../agent"
import { Database } from "../database/database"
import { EventV2 } from "../event"
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
import { Client } from "@opencode-ai/util/client"
import { App } from "../app"
import { llmClient } from "../effect/app-node-platform"
import { SessionEvent } from "./event"
import { SessionHistory } from "./history"
@ -18,7 +18,7 @@ import { SessionUsage } from "./usage"
const MAX_LENGTH = 100
type Dependencies = {
readonly client: string
readonly app: App.Info
readonly events: EventV2.Interface
readonly llm: {
readonly stream: (request: LLMRequest) => Stream.Stream<LLMEvent, LLMError>
@ -68,7 +68,7 @@ const make = (dependencies: Dependencies) => {
.stream(
LLM.request({
model: resolved.model,
http: { headers: SessionModelHeaders.make(session, dependencies.client) },
http: { headers: SessionModelHeaders.make(session, dependencies.app) },
system: agent.system,
messages: [Message.user(firstUser.text)],
tools: [],
@ -112,8 +112,8 @@ export const layer = Layer.effect(
const agents = yield* AgentV2.Service
const models = yield* SessionRunnerModel.Service
const database = yield* Database.Service
const client = yield* Client.Name
const title = make({ events, llm, agents, models, client })
const app = yield* App.Metadata
const title = make({ events, llm, agents, models, app })
return Service.of({
generateForFirstPrompt: (session) => title.generateForFirstPrompt(database.db, session),
})
@ -123,5 +123,5 @@ export const layer = Layer.effect(
export const node = makeLocationNode({
service: Service,
layer,
deps: [EventV2.node, llmClient, AgentV2.node, SessionRunnerModel.node, Database.node, Client.node],
deps: [EventV2.node, llmClient, AgentV2.node, SessionRunnerModel.node, Database.node, App.node],
})