Compare commits
27
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7bf95ba7bf | ||
|
|
e2cbe4b961 | ||
|
|
9ec65c5e4b | ||
|
|
55cfacc6f4 | ||
|
|
b51975fd67 | ||
|
|
ce1b5ee496 | ||
|
|
647671dbe6 | ||
|
|
3977b9b8c9 | ||
|
|
8905b31bdb | ||
|
|
46af0aca8e | ||
|
|
11afe56f63 | ||
|
|
5288e9cb86 | ||
|
|
61468546be | ||
|
|
aebcc8ac32 | ||
|
|
368354779b | ||
|
|
ca0c1632ea | ||
|
|
6498a4624c | ||
|
|
806d8a84b4 | ||
|
|
961e605c73 | ||
|
|
041d463210 | ||
|
|
f82f29cd24 | ||
|
|
6015a47dae | ||
|
|
6c3c7ceb2f | ||
|
|
1fb54efdd2 | ||
|
|
d45d5d664c | ||
|
|
323ce486a5 | ||
|
|
390b660c81 |
@@ -65,4 +65,3 @@
|
||||
| 2025-08-29 | 256,045 (+3,249) | 211,075 (+5,833) | 467,120 (+9,082) |
|
||||
| 2025-08-30 | 258,863 (+2,818) | 212,397 (+1,322) | 471,260 (+4,140) |
|
||||
| 2025-08-31 | 262,004 (+3,141) | 213,944 (+1,547) | 475,948 (+4,688) |
|
||||
| 2025-09-01 | 265,359 (+3,355) | 215,115 (+1,171) | 480,474 (+4,526) |
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"dev:remote": "VITE_AUTH_URL=https://auth.dev.opencode.ai bun sst shell --stage=dev bun dev",
|
||||
"build": "vinxi build",
|
||||
"start": "vinxi start",
|
||||
"version": "0.6.0"
|
||||
"version": "0.5.29"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ibm/plex": "6.4.1",
|
||||
|
||||
@@ -52,7 +52,7 @@ export const getActor = query(async (): Promise<Actor.Info> => {
|
||||
}
|
||||
}
|
||||
const workspaceHint = splits[1]
|
||||
const accounts = Object.keys(auth.data.account ?? {})
|
||||
const accounts = Object.keys(auth.data.account)
|
||||
const result = await Database.transaction(async (tx) => {
|
||||
return await tx
|
||||
.select({
|
||||
|
||||
@@ -20,6 +20,4 @@ export default createHandler(() => (
|
||||
</html>
|
||||
)}
|
||||
/>
|
||||
), {
|
||||
mode: "sync",
|
||||
})
|
||||
))
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import type { APIEvent } from "@solidjs/start/server"
|
||||
import { Resource } from "@opencode/cloud-resource"
|
||||
import { json } from "@solidjs/router"
|
||||
import { Database } from "@opencode/cloud-core/drizzle/index.js"
|
||||
import { UserTable } from "@opencode/cloud-core/schema/user.sql.js"
|
||||
|
||||
export async function GET(evt: APIEvent) {
|
||||
return json({
|
||||
data: await Database.use(async (tx) => {
|
||||
const result = await tx.$count(UserTable)
|
||||
return result
|
||||
}),
|
||||
data: Resource.Database.host,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -30,9 +30,7 @@ const logout = action(async () => {
|
||||
})
|
||||
|
||||
export default function WorkspaceLayout(props: RouteSectionProps) {
|
||||
const userInfo = createAsync(() => getUserInfo(), {
|
||||
deferStream: true,
|
||||
})
|
||||
const userInfo = createAsync(() => getUserInfo())
|
||||
return (
|
||||
<main data-page="workspace">
|
||||
<header data-component="workspace-header">
|
||||
@@ -42,7 +40,9 @@ export default function WorkspaceLayout(props: RouteSectionProps) {
|
||||
</a>
|
||||
</div>
|
||||
<div data-slot="header-actions">
|
||||
<span>{userInfo()?.user.email}</span>
|
||||
{userInfo() &&
|
||||
<span>{userInfo()!.user.email}</span>
|
||||
}
|
||||
<form action={logout} method="post">
|
||||
<button type="submit" formaction={logout}>Logout</button>
|
||||
</form>
|
||||
|
||||
@@ -63,14 +63,13 @@ const createPortalUrl = action(async (returnUrl: string) => {
|
||||
return withActor(() => Billing.generatePortalUrl({ returnUrl }))
|
||||
}, "portalUrl")
|
||||
|
||||
export default function () {
|
||||
export default function() {
|
||||
const actor = createAsync(() => getActor())
|
||||
|
||||
/////////////////
|
||||
// Keys section
|
||||
/////////////////
|
||||
const keys = createAsync(() => listKeys(), {
|
||||
deferStream: true,
|
||||
})
|
||||
const keys = createAsync(() => listKeys())
|
||||
const createKeyAction = useAction(createKey)
|
||||
const removeKeyAction = useAction(removeKey)
|
||||
const createKeySubmission = useSubmission(createKey)
|
||||
@@ -158,9 +157,7 @@ export default function () {
|
||||
/////////////////
|
||||
// Billing section
|
||||
/////////////////
|
||||
const billingInfo = createAsync(() => getBillingInfo(), {
|
||||
deferStream: true,
|
||||
})
|
||||
const billingInfo = createAsync(() => getBillingInfo())
|
||||
const createCheckoutUrlAction = useAction(createCheckoutUrl)
|
||||
const createCheckoutUrlSubmission = useSubmission(createCheckoutUrl)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode/cloud-core",
|
||||
"version": "0.6.0",
|
||||
"version": "0.5.29",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
|
||||
@@ -15,12 +15,12 @@ const init = () => {
|
||||
ssl: {
|
||||
rejectUnauthorized: false,
|
||||
},
|
||||
max: 6,
|
||||
max: 1,
|
||||
})
|
||||
return drizzle(client, {})
|
||||
}
|
||||
|
||||
const createClient = init
|
||||
const createClient = "NODE_ENV" in process.env ? memo(init) : init
|
||||
|
||||
import { PgTransaction, type PgTransactionConfig } from "drizzle-orm/pg-core"
|
||||
import type { ExtractTablesWithRelations } from "drizzle-orm"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode/cloud-function",
|
||||
"version": "0.6.0",
|
||||
"version": "0.5.29",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ export const database = new sst.Linkable("Database", {
|
||||
database: "postgres",
|
||||
username: DATABASE_USERNAME.value,
|
||||
password: DATABASE_PASSWORD.value,
|
||||
port: 6432,
|
||||
port: 5432,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode/function",
|
||||
"version": "0.6.0",
|
||||
"version": "0.5.29",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "0.6.0",
|
||||
"version": "0.5.29",
|
||||
"name": "opencode",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
|
||||
@@ -10,7 +10,6 @@ import { bootstrap } from "../bootstrap"
|
||||
import { MessageV2 } from "../../session/message-v2"
|
||||
import { Identifier } from "../../id/id"
|
||||
import { Agent } from "../../agent/agent"
|
||||
import { Command } from "../../command"
|
||||
|
||||
const TOOL: Record<string, [string, string]> = {
|
||||
todowrite: ["Todo", UI.Style.TEXT_WARNING_BOLD],
|
||||
@@ -36,10 +35,6 @@ export const RunCommand = cmd({
|
||||
array: true,
|
||||
default: [],
|
||||
})
|
||||
.option("command", {
|
||||
describe: "the command to run, use message for args",
|
||||
type: "string",
|
||||
})
|
||||
.option("continue", {
|
||||
alias: ["c"],
|
||||
describe: "continue the last session",
|
||||
@@ -69,19 +64,12 @@ export const RunCommand = cmd({
|
||||
|
||||
if (!process.stdin.isTTY) message += "\n" + (await Bun.stdin.text())
|
||||
|
||||
if (message.trim().length === 0 && !args.command) {
|
||||
UI.error("You must provide a message or a command")
|
||||
if (message.trim().length === 0) {
|
||||
UI.error("Message cannot be empty")
|
||||
return
|
||||
}
|
||||
|
||||
await bootstrap(process.cwd(), async () => {
|
||||
if (args.command) {
|
||||
const exists = await Command.get(args.command)
|
||||
if (!exists) {
|
||||
UI.error(`Command "${args.command}" not found`)
|
||||
return
|
||||
}
|
||||
}
|
||||
const session = await (async () => {
|
||||
if (args.continue) {
|
||||
const it = Session.list()
|
||||
@@ -184,26 +172,12 @@ export const RunCommand = cmd({
|
||||
UI.error(err)
|
||||
})
|
||||
|
||||
if (args.command) {
|
||||
await Session.command({
|
||||
messageID: Identifier.ascending("message"),
|
||||
sessionID: session.id,
|
||||
agent: agent.name,
|
||||
model: providerID + "/" + modelID,
|
||||
command: args.command,
|
||||
arguments: message,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const messageID = Identifier.ascending("message")
|
||||
const result = await Session.prompt({
|
||||
const result = await Session.chat({
|
||||
sessionID: session.id,
|
||||
messageID,
|
||||
model: {
|
||||
providerID,
|
||||
modelID,
|
||||
},
|
||||
providerID,
|
||||
modelID,
|
||||
agent: agent.name,
|
||||
parts: [
|
||||
{
|
||||
@@ -216,7 +190,7 @@ export const RunCommand = cmd({
|
||||
|
||||
const isPiped = !process.stdout.isTTY
|
||||
if (isPiped) {
|
||||
const match = result.parts.findLast((x: any) => x.type === "text") as any
|
||||
const match = result.parts.findLast((x) => x.type === "text")
|
||||
if (match) process.stdout.write(UI.markdown(match.text))
|
||||
if (errorMsg) process.stdout.write(errorMsg)
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ export namespace LSPServer {
|
||||
}
|
||||
|
||||
export const Gopls: Info = {
|
||||
id: "gopls",
|
||||
id: "golang",
|
||||
root: async (file) => {
|
||||
const work = await NearestRoot(["go.work"])(file)
|
||||
if (work) return work
|
||||
|
||||
@@ -153,10 +153,7 @@ export namespace Provider {
|
||||
options: Record<string, any>
|
||||
}
|
||||
} = {}
|
||||
const models = new Map<
|
||||
string,
|
||||
{ providerID: string; modelID: string; info: ModelsDev.Model; language: LanguageModel }
|
||||
>()
|
||||
const models = new Map<string, { info: ModelsDev.Model; language: LanguageModel }>()
|
||||
const sdk = new Map<string, SDK>()
|
||||
|
||||
log.info("init")
|
||||
@@ -365,14 +362,10 @@ export namespace Provider {
|
||||
const language = provider.getModel ? await provider.getModel(sdk, modelID) : sdk.languageModel(modelID)
|
||||
log.info("found", { providerID, modelID })
|
||||
s.models.set(key, {
|
||||
providerID,
|
||||
modelID,
|
||||
info,
|
||||
language,
|
||||
})
|
||||
return {
|
||||
modelID,
|
||||
providerID,
|
||||
info,
|
||||
language,
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export const ProjectRoute = new Hono()
|
||||
"/current",
|
||||
describeRoute({
|
||||
description: "Get the current project",
|
||||
operationId: "project.current",
|
||||
operationId: "butt.current",
|
||||
responses: {
|
||||
200: {
|
||||
description: "Current project",
|
||||
|
||||
@@ -53,9 +53,6 @@ export namespace Server {
|
||||
const app = new Hono()
|
||||
export const App = app
|
||||
.onError((err, c) => {
|
||||
log.error("failed", {
|
||||
error: err,
|
||||
})
|
||||
if (err instanceof NamedError) {
|
||||
return c.json(err.toObject(), {
|
||||
status: 400,
|
||||
@@ -609,7 +606,7 @@ export namespace Server {
|
||||
"/session/:id/message",
|
||||
describeRoute({
|
||||
description: "Create and send a new message to a session",
|
||||
operationId: "session.prompt",
|
||||
operationId: "session.chat",
|
||||
responses: {
|
||||
200: {
|
||||
description: "Created message",
|
||||
@@ -632,11 +629,11 @@ export namespace Server {
|
||||
id: z.string().openapi({ description: "Session ID" }),
|
||||
}),
|
||||
),
|
||||
zValidator("json", Session.PromptInput.omit({ sessionID: true })),
|
||||
zValidator("json", Session.ChatInput.omit({ sessionID: true })),
|
||||
async (c) => {
|
||||
const sessionID = c.req.valid("param").id
|
||||
const body = c.req.valid("json")
|
||||
const msg = await Session.prompt({ ...body, sessionID })
|
||||
const msg = await Session.chat({ ...body, sessionID })
|
||||
return c.json(msg)
|
||||
},
|
||||
)
|
||||
|
||||
@@ -364,15 +364,11 @@ export namespace Session {
|
||||
return part
|
||||
}
|
||||
|
||||
export const PromptInput = z.object({
|
||||
export const ChatInput = z.object({
|
||||
sessionID: Identifier.schema("session"),
|
||||
messageID: Identifier.schema("message").optional(),
|
||||
model: z
|
||||
.object({
|
||||
providerID: z.string(),
|
||||
modelID: z.string(),
|
||||
})
|
||||
.optional(),
|
||||
providerID: z.string(),
|
||||
modelID: z.string(),
|
||||
agent: z.string().optional(),
|
||||
system: z.string().optional(),
|
||||
tools: z.record(z.boolean()).optional(),
|
||||
@@ -411,10 +407,10 @@ export namespace Session {
|
||||
]),
|
||||
),
|
||||
})
|
||||
export type ChatInput = z.infer<typeof PromptInput>
|
||||
export type ChatInput = z.infer<typeof ChatInput>
|
||||
|
||||
export async function prompt(
|
||||
input: z.infer<typeof PromptInput>,
|
||||
export async function chat(
|
||||
input: z.infer<typeof ChatInput>,
|
||||
): Promise<{ info: MessageV2.Assistant; parts: MessageV2.Part[] }> {
|
||||
const l = log.clone().tag("session", input.sessionID)
|
||||
l.info("chatting")
|
||||
@@ -656,16 +652,7 @@ export namespace Session {
|
||||
})
|
||||
}
|
||||
|
||||
const agent = await Agent.get(inputAgent)
|
||||
const model = await (async () => {
|
||||
if (input.model) {
|
||||
return input.model
|
||||
}
|
||||
if (agent.model) {
|
||||
return agent.model
|
||||
}
|
||||
return Provider.defaultModel()
|
||||
})().then((x) => Provider.getModel(x.providerID, x.modelID))
|
||||
const model = await Provider.getModel(input.providerID, input.modelID)
|
||||
let msgs = await messages(input.sessionID)
|
||||
|
||||
const previous = msgs.filter((x) => x.info.role === "assistant").at(-1)?.info as MessageV2.Assistant
|
||||
@@ -680,10 +667,10 @@ export namespace Session {
|
||||
|
||||
await summarize({
|
||||
sessionID: input.sessionID,
|
||||
providerID: model.providerID,
|
||||
modelID: model.info.id,
|
||||
providerID: input.providerID,
|
||||
modelID: input.modelID,
|
||||
})
|
||||
return prompt(input)
|
||||
return chat(input)
|
||||
}
|
||||
}
|
||||
using abort = lock(input.sessionID)
|
||||
@@ -692,17 +679,17 @@ export namespace Session {
|
||||
if (lastSummary) msgs = msgs.filter((msg) => msg.info.id >= lastSummary.info.id)
|
||||
|
||||
if (msgs.filter((m) => m.info.role === "user").length === 1 && !session.parentID && isDefaultTitle(session.title)) {
|
||||
const small = (await Provider.getSmallModel(model.providerID)) ?? model
|
||||
const small = (await Provider.getSmallModel(input.providerID)) ?? model
|
||||
generateText({
|
||||
maxOutputTokens: small.info.reasoning ? 1024 : 20,
|
||||
providerOptions: {
|
||||
[model.providerID]: {
|
||||
[input.providerID]: {
|
||||
...small.info.options,
|
||||
...ProviderTransform.options(small.providerID, small.modelID, input.sessionID),
|
||||
...ProviderTransform.options(input.providerID, small.info.id, input.sessionID),
|
||||
},
|
||||
},
|
||||
messages: [
|
||||
...SystemPrompt.title(model.providerID).map(
|
||||
...SystemPrompt.title(input.providerID).map(
|
||||
(x): ModelMessage => ({
|
||||
role: "system",
|
||||
content: x,
|
||||
@@ -737,6 +724,7 @@ export namespace Session {
|
||||
})
|
||||
}
|
||||
|
||||
const agent = await Agent.get(inputAgent)
|
||||
if (agent.name === "plan") {
|
||||
msgs.at(-1)?.parts.push({
|
||||
id: Identifier.ascending("part"),
|
||||
@@ -759,12 +747,12 @@ export namespace Session {
|
||||
synthetic: true,
|
||||
})
|
||||
}
|
||||
let system = SystemPrompt.header(model.providerID)
|
||||
let system = SystemPrompt.header(input.providerID)
|
||||
system.push(
|
||||
...(() => {
|
||||
if (input.system) return [input.system]
|
||||
if (agent.prompt) return [agent.prompt]
|
||||
return SystemPrompt.provider(model.modelID)
|
||||
return SystemPrompt.provider(input.modelID)
|
||||
})(),
|
||||
)
|
||||
system.push(...(await SystemPrompt.environment()))
|
||||
@@ -789,8 +777,8 @@ export namespace Session {
|
||||
reasoning: 0,
|
||||
cache: { read: 0, write: 0 },
|
||||
},
|
||||
modelID: model.modelID,
|
||||
providerID: model.providerID,
|
||||
modelID: input.modelID,
|
||||
providerID: input.providerID,
|
||||
time: {
|
||||
created: Date.now(),
|
||||
},
|
||||
@@ -808,10 +796,10 @@ export namespace Session {
|
||||
|
||||
const enabledTools = pipe(
|
||||
agent.tools,
|
||||
mergeDeep(await ToolRegistry.enabled(model.providerID, model.modelID, agent)),
|
||||
mergeDeep(await ToolRegistry.enabled(input.providerID, input.modelID, agent)),
|
||||
mergeDeep(input.tools ?? {}),
|
||||
)
|
||||
for (const item of await ToolRegistry.tools(model.providerID, model.modelID)) {
|
||||
for (const item of await ToolRegistry.tools(input.providerID, input.modelID)) {
|
||||
if (Wildcard.all(item.id, enabledTools) === false) continue
|
||||
tools[item.id] = tool({
|
||||
id: item.id as any,
|
||||
@@ -921,16 +909,16 @@ export namespace Session {
|
||||
"chat.params",
|
||||
{
|
||||
model: model.info,
|
||||
provider: await Provider.getProvider(model.providerID),
|
||||
provider: await Provider.getProvider(input.providerID),
|
||||
message: userMsg,
|
||||
},
|
||||
{
|
||||
temperature: model.info.temperature
|
||||
? (agent.temperature ?? ProviderTransform.temperature(model.providerID, model.modelID))
|
||||
? (agent.temperature ?? ProviderTransform.temperature(input.providerID, input.modelID))
|
||||
: undefined,
|
||||
topP: agent.topP ?? ProviderTransform.topP(model.providerID, model.modelID),
|
||||
topP: agent.topP ?? ProviderTransform.topP(input.providerID, input.modelID),
|
||||
options: {
|
||||
...ProviderTransform.options(model.providerID, model.modelID, input.sessionID),
|
||||
...ProviderTransform.options(input.providerID, input.modelID, input.sessionID),
|
||||
...model.info.options,
|
||||
...agent.options,
|
||||
},
|
||||
@@ -974,8 +962,8 @@ export namespace Session {
|
||||
reasoning: 0,
|
||||
cache: { read: 0, write: 0 },
|
||||
},
|
||||
modelID: model.modelID,
|
||||
providerID: model.providerID,
|
||||
modelID: input.modelID,
|
||||
providerID: input.providerID,
|
||||
mode: inputAgent,
|
||||
time: {
|
||||
created: Date.now(),
|
||||
@@ -999,7 +987,7 @@ export namespace Session {
|
||||
}
|
||||
},
|
||||
headers:
|
||||
model.providerID === "opencode"
|
||||
input.providerID === "opencode"
|
||||
? {
|
||||
"x-opencode-session": input.sessionID,
|
||||
"x-opencode-request": userMsg.id,
|
||||
@@ -1022,7 +1010,7 @@ export namespace Session {
|
||||
return false
|
||||
},
|
||||
providerOptions: {
|
||||
[model.providerID]: params.options,
|
||||
[input.providerID]: params.options,
|
||||
},
|
||||
temperature: params.temperature,
|
||||
topP: params.topP,
|
||||
@@ -1043,7 +1031,7 @@ export namespace Session {
|
||||
async transformParams(args) {
|
||||
if (args.type === "stream") {
|
||||
// @ts-expect-error
|
||||
args.params.prompt = ProviderTransform.message(args.params.prompt, model.providerID, model.modelID)
|
||||
args.params.prompt = ProviderTransform.message(args.params.prompt, input.providerID, input.modelID)
|
||||
}
|
||||
return args.params
|
||||
},
|
||||
@@ -1056,7 +1044,7 @@ export namespace Session {
|
||||
const unprocessed = queued.find((x) => !x.processed)
|
||||
if (unprocessed) {
|
||||
unprocessed.processed = true
|
||||
return prompt(unprocessed.input)
|
||||
return chat(unprocessed.input)
|
||||
}
|
||||
for (const item of queued) {
|
||||
item.callback(result)
|
||||
@@ -1232,9 +1220,16 @@ export namespace Session {
|
||||
const fileRegex = /@([^\s]+)/g
|
||||
|
||||
export async function command(input: CommandInput) {
|
||||
log.info("command", input)
|
||||
const command = await Command.get(input.command)
|
||||
const agent = command.agent ?? input.agent ?? "build"
|
||||
const fmtModel = (model: { providerID: string; modelID: string }) => `${model.providerID}/${model.modelID}`
|
||||
|
||||
const model =
|
||||
command.model ??
|
||||
(command.agent && (await Agent.get(command.agent).then((x) => (x.model ? fmtModel(x.model) : undefined)))) ??
|
||||
input.model ??
|
||||
(input.agent && (await Agent.get(input.agent).then((x) => (x.model ? fmtModel(x.model) : undefined)))) ??
|
||||
fmtModel(await Provider.defaultModel())
|
||||
|
||||
let template = command.template.replace("$ARGUMENTS", input.arguments)
|
||||
|
||||
@@ -1278,18 +1273,10 @@ export namespace Session {
|
||||
})
|
||||
}
|
||||
|
||||
return prompt({
|
||||
return chat({
|
||||
sessionID: input.sessionID,
|
||||
messageID: input.messageID,
|
||||
model: (() => {
|
||||
if (input.model) {
|
||||
return Provider.parseModel(input.model)
|
||||
}
|
||||
if (command.model) {
|
||||
return Provider.parseModel(command.model)
|
||||
}
|
||||
return undefined
|
||||
})(),
|
||||
...Provider.parseModel(model!),
|
||||
agent,
|
||||
parts,
|
||||
})
|
||||
@@ -1656,7 +1643,7 @@ export namespace Session {
|
||||
const filtered = msgs.filter((msg) => !lastSummary || msg.info.id >= lastSummary.info.id)
|
||||
const model = await Provider.getModel(input.providerID, input.modelID)
|
||||
const system = [
|
||||
...SystemPrompt.summarize(model.providerID),
|
||||
...SystemPrompt.summarize(input.providerID),
|
||||
...(await SystemPrompt.environment()),
|
||||
...(await SystemPrompt.custom()),
|
||||
]
|
||||
@@ -1674,7 +1661,7 @@ export namespace Session {
|
||||
summary: true,
|
||||
cost: 0,
|
||||
modelID: input.modelID,
|
||||
providerID: model.providerID,
|
||||
providerID: input.providerID,
|
||||
tokens: {
|
||||
input: 0,
|
||||
output: 0,
|
||||
@@ -1783,13 +1770,11 @@ export namespace Session {
|
||||
providerID: string
|
||||
messageID: string
|
||||
}) {
|
||||
await Session.prompt({
|
||||
await Session.chat({
|
||||
sessionID: input.sessionID,
|
||||
messageID: input.messageID,
|
||||
model: {
|
||||
providerID: input.providerID,
|
||||
modelID: input.modelID,
|
||||
},
|
||||
providerID: input.providerID,
|
||||
modelID: input.modelID,
|
||||
parts: [
|
||||
{
|
||||
id: Identifier.ascending("part"),
|
||||
|
||||
@@ -30,7 +30,6 @@ export namespace Storage {
|
||||
if (worktree) break
|
||||
}
|
||||
if (!worktree) continue
|
||||
if (!(await fs.exists(worktree))) continue
|
||||
const [id] = await $`git rev-list --max-parents=0 --all`
|
||||
.quiet()
|
||||
.nothrow()
|
||||
|
||||
@@ -51,13 +51,11 @@ export const TaskTool = Tool.define("task", async () => {
|
||||
ctx.abort.addEventListener("abort", () => {
|
||||
Session.abort(session.id)
|
||||
})
|
||||
const result = await Session.prompt({
|
||||
const result = await Session.chat({
|
||||
messageID,
|
||||
sessionID: session.id,
|
||||
model: {
|
||||
modelID: model.modelID,
|
||||
providerID: model.providerID,
|
||||
},
|
||||
modelID: model.modelID,
|
||||
providerID: model.providerID,
|
||||
agent: agent.name,
|
||||
tools: {
|
||||
todowrite: false,
|
||||
@@ -77,9 +75,9 @@ export const TaskTool = Tool.define("task", async () => {
|
||||
return {
|
||||
title: params.description,
|
||||
metadata: {
|
||||
summary: result.parts.filter((x: any) => x.type === "tool"),
|
||||
summary: result.parts.filter((x) => x.type === "tool"),
|
||||
},
|
||||
output: (result.parts.findLast((x: any) => x.type === "text") as any)?.text ?? "",
|
||||
output: result.parts.findLast((x) => x.type === "text")?.text ?? "",
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "0.6.0",
|
||||
"version": "0.5.29",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"typecheck": "tsc --noEmit"
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import { Plugin } from "./index"
|
||||
|
||||
export const ExamplePlugin: Plugin = async ({
|
||||
client: _client,
|
||||
$: _shell,
|
||||
project: _project,
|
||||
directory: _directory,
|
||||
worktree: _worktree,
|
||||
}) => {
|
||||
export const ExamplePlugin: Plugin = async ({ client, $ }) => {
|
||||
return {
|
||||
permission: {},
|
||||
async "chat.params"(_input, output) {
|
||||
async "chat.params"(input, output) {
|
||||
output.topP = 1
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
".": "0.8.0"
|
||||
".": "0.5.0"
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
configured_endpoints: 43
|
||||
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-97b61518d8666ea7cb310af04248e00bcf8dc9753ba3c7e84471df72b3232004.yml
|
||||
openapi_spec_hash: a3500531973ad999c350b87c21aa3ab8
|
||||
config_hash: 026ef000d34bf2f930e7b41e77d2d3ff
|
||||
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-24d6bfcc66bba2e3a826fdad7e48a474c5aa9193a6bb89dc8ab1feb1f3d9bf72.yml
|
||||
openapi_spec_hash: db8b553192d9027e1f9254096406cfc2
|
||||
config_hash: 1b0d220e033fe9f683abf7048e7ad076
|
||||
|
||||
@@ -1,29 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## 0.8.0 (2025-09-01)
|
||||
|
||||
Full Changelog: [v0.7.0...v0.8.0](https://github.com/sst/opencode-sdk-go/compare/v0.7.0...v0.8.0)
|
||||
|
||||
### Features
|
||||
|
||||
* **api:** api update ([ae87a71](https://github.com/sst/opencode-sdk-go/commit/ae87a71949994590ace8285a39f0991ef34b664d))
|
||||
|
||||
## 0.7.0 (2025-09-01)
|
||||
|
||||
Full Changelog: [v0.6.0...v0.7.0](https://github.com/sst/opencode-sdk-go/compare/v0.6.0...v0.7.0)
|
||||
|
||||
### Features
|
||||
|
||||
* **api:** api update ([64bb1b1](https://github.com/sst/opencode-sdk-go/commit/64bb1b1ee0cbe153abc6fb7bd9703b47911724d4))
|
||||
|
||||
## 0.6.0 (2025-09-01)
|
||||
|
||||
Full Changelog: [v0.5.0...v0.6.0](https://github.com/sst/opencode-sdk-go/compare/v0.5.0...v0.6.0)
|
||||
|
||||
### Features
|
||||
|
||||
* **api:** api update ([928e384](https://github.com/sst/opencode-sdk-go/commit/928e3843355f96899f046f002b84372281dad0c8))
|
||||
|
||||
## 0.5.0 (2025-08-31)
|
||||
|
||||
Full Changelog: [v0.4.0...v0.5.0](https://github.com/sst/opencode-sdk-go/compare/v0.4.0...v0.5.0)
|
||||
|
||||
@@ -24,7 +24,7 @@ Or to pin the version:
|
||||
<!-- x-release-please-start-version -->
|
||||
|
||||
```sh
|
||||
go get -u 'github.com/sst/opencode-sdk-go@v0.8.0'
|
||||
go get -u 'github.com/sst/opencode-sdk-go@v0.5.0'
|
||||
```
|
||||
|
||||
<!-- x-release-please-end -->
|
||||
|
||||
@@ -143,10 +143,10 @@ Response Types:
|
||||
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolStatePending">ToolStatePending</a>
|
||||
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolStateRunning">ToolStateRunning</a>
|
||||
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#UserMessage">UserMessage</a>
|
||||
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionChatResponse">SessionChatResponse</a>
|
||||
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionCommandResponse">SessionCommandResponse</a>
|
||||
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionMessageResponse">SessionMessageResponse</a>
|
||||
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionMessagesResponse">SessionMessagesResponse</a>
|
||||
- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionPromptResponse">SessionPromptResponse</a>
|
||||
|
||||
Methods:
|
||||
|
||||
@@ -155,13 +155,13 @@ Methods:
|
||||
- <code title="get /session">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionListParams">SessionListParams</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="delete /session/{id}">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionDeleteParams">SessionDeleteParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="post /session/{id}/abort">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Abort">Abort</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionAbortParams">SessionAbortParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="post /session/{id}/message">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Chat">Chat</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, params <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionChatParams">SessionChatParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionChatResponse">SessionChatResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="get /session/{id}/children">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Children">Children</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionChildrenParams">SessionChildrenParams</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="post /session/{id}/command">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Command">Command</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, params <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionCommandParams">SessionCommandParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionCommandResponse">SessionCommandResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="get /session/{id}">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionGetParams">SessionGetParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="post /session/{id}/init">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Init">Init</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, params <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionInitParams">SessionInitParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="get /session/{id}/message/{messageID}">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Message">Message</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, messageID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionMessageParams">SessionMessageParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionMessageResponse">SessionMessageResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="get /session/{id}/message">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Messages">Messages</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionMessagesParams">SessionMessagesParams</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionMessagesResponse">SessionMessagesResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="post /session/{id}/message">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Prompt">Prompt</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, params <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionPromptParams">SessionPromptParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionPromptResponse">SessionPromptResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="post /session/{id}/revert">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Revert">Revert</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, params <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionRevertParams">SessionRevertParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="post /session/{id}/share">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Share">Share</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionShareParams">SessionShareParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="post /session/{id}/shell">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Shell">Shell</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, params <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionShellParams">SessionShellParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AssistantMessage">AssistantMessage</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/sst/opencode-sdk-go/internal/param"
|
||||
"github.com/sst/opencode-sdk-go/internal/requestconfig"
|
||||
"github.com/sst/opencode-sdk-go/option"
|
||||
"github.com/sst/opencode-sdk-go/shared"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
@@ -1651,13 +1650,10 @@ func (r configProviderModelsLimitJSON) RawJSON() string {
|
||||
}
|
||||
|
||||
type ConfigProviderOptions struct {
|
||||
APIKey string `json:"apiKey"`
|
||||
BaseURL string `json:"baseURL"`
|
||||
// Timeout in milliseconds for requests to this provider. Default is 300000 (5
|
||||
// minutes). Set to false to disable timeout.
|
||||
Timeout ConfigProviderOptionsTimeoutUnion `json:"timeout"`
|
||||
ExtraFields map[string]interface{} `json:"-,extras"`
|
||||
JSON configProviderOptionsJSON `json:"-"`
|
||||
APIKey string `json:"apiKey"`
|
||||
BaseURL string `json:"baseURL"`
|
||||
ExtraFields map[string]interface{} `json:"-,extras"`
|
||||
JSON configProviderOptionsJSON `json:"-"`
|
||||
}
|
||||
|
||||
// configProviderOptionsJSON contains the JSON metadata for the struct
|
||||
@@ -1665,7 +1661,6 @@ type ConfigProviderOptions struct {
|
||||
type configProviderOptionsJSON struct {
|
||||
APIKey apijson.Field
|
||||
BaseURL apijson.Field
|
||||
Timeout apijson.Field
|
||||
raw string
|
||||
ExtraFields map[string]apijson.Field
|
||||
}
|
||||
@@ -1678,33 +1673,6 @@ func (r configProviderOptionsJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
// Timeout in milliseconds for requests to this provider. Default is 300000 (5
|
||||
// minutes). Set to false to disable timeout.
|
||||
//
|
||||
// Union satisfied by [shared.UnionInt] or [shared.UnionBool].
|
||||
type ConfigProviderOptionsTimeoutUnion interface {
|
||||
ImplementsConfigProviderOptionsTimeoutUnion()
|
||||
}
|
||||
|
||||
func init() {
|
||||
apijson.RegisterUnion(
|
||||
reflect.TypeOf((*ConfigProviderOptionsTimeoutUnion)(nil)).Elem(),
|
||||
"",
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.Number,
|
||||
Type: reflect.TypeOf(shared.UnionInt(0)),
|
||||
},
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.True,
|
||||
Type: reflect.TypeOf(shared.UnionBool(false)),
|
||||
},
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.False,
|
||||
Type: reflect.TypeOf(shared.UnionBool(false)),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// Control sharing behavior:'manual' allows manual sharing via commands, 'auto'
|
||||
// enables automatic sharing, 'disabled' disables all sharing
|
||||
type ConfigShare string
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
package internal
|
||||
|
||||
const PackageVersion = "0.8.0" // x-release-please-version
|
||||
const PackageVersion = "0.5.0" // x-release-please-version
|
||||
|
||||
@@ -42,19 +42,15 @@ func (r *PathService) Get(ctx context.Context, query PathGetParams, opts ...opti
|
||||
}
|
||||
|
||||
type Path struct {
|
||||
Config string `json:"config,required"`
|
||||
Directory string `json:"directory,required"`
|
||||
State string `json:"state,required"`
|
||||
Worktree string `json:"worktree,required"`
|
||||
JSON pathJSON `json:"-"`
|
||||
Config string `json:"config,required"`
|
||||
State string `json:"state,required"`
|
||||
JSON pathJSON `json:"-"`
|
||||
}
|
||||
|
||||
// pathJSON contains the JSON metadata for the struct [Path]
|
||||
type pathJSON struct {
|
||||
Config apijson.Field
|
||||
Directory apijson.Field
|
||||
State apijson.Field
|
||||
Worktree apijson.Field
|
||||
raw string
|
||||
ExtraFields map[string]apijson.Field
|
||||
}
|
||||
|
||||
+102
-110
@@ -92,6 +92,18 @@ func (r *SessionService) Abort(ctx context.Context, id string, body SessionAbort
|
||||
return
|
||||
}
|
||||
|
||||
// Create and send a new message to a session
|
||||
func (r *SessionService) Chat(ctx context.Context, id string, params SessionChatParams, opts ...option.RequestOption) (res *SessionChatResponse, err error) {
|
||||
opts = append(r.Options[:], opts...)
|
||||
if id == "" {
|
||||
err = errors.New("missing required id parameter")
|
||||
return
|
||||
}
|
||||
path := fmt.Sprintf("session/%s/message", id)
|
||||
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &res, opts...)
|
||||
return
|
||||
}
|
||||
|
||||
// Get a session's children
|
||||
func (r *SessionService) Children(ctx context.Context, id string, query SessionChildrenParams, opts ...option.RequestOption) (res *[]Session, err error) {
|
||||
opts = append(r.Options[:], opts...)
|
||||
@@ -168,18 +180,6 @@ func (r *SessionService) Messages(ctx context.Context, id string, query SessionM
|
||||
return
|
||||
}
|
||||
|
||||
// Create and send a new message to a session
|
||||
func (r *SessionService) Prompt(ctx context.Context, id string, params SessionPromptParams, opts ...option.RequestOption) (res *SessionPromptResponse, err error) {
|
||||
opts = append(r.Options[:], opts...)
|
||||
if id == "" {
|
||||
err = errors.New("missing required id parameter")
|
||||
return
|
||||
}
|
||||
path := fmt.Sprintf("session/%s/message", id)
|
||||
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &res, opts...)
|
||||
return
|
||||
}
|
||||
|
||||
// Revert a message
|
||||
func (r *SessionService) Revert(ctx context.Context, id string, params SessionRevertParams, opts ...option.RequestOption) (res *Session, err error) {
|
||||
opts = append(r.Options[:], opts...)
|
||||
@@ -333,7 +333,7 @@ func (r AgentPartInputParam) MarshalJSON() (data []byte, err error) {
|
||||
return apijson.MarshalRoot(r)
|
||||
}
|
||||
|
||||
func (r AgentPartInputParam) implementsSessionPromptParamsPartUnion() {}
|
||||
func (r AgentPartInputParam) implementsSessionChatParamsPartUnion() {}
|
||||
|
||||
type AgentPartInputType string
|
||||
|
||||
@@ -709,7 +709,7 @@ func (r FilePartInputParam) MarshalJSON() (data []byte, err error) {
|
||||
return apijson.MarshalRoot(r)
|
||||
}
|
||||
|
||||
func (r FilePartInputParam) implementsSessionPromptParamsPartUnion() {}
|
||||
func (r FilePartInputParam) implementsSessionChatParamsPartUnion() {}
|
||||
|
||||
type FilePartInputType string
|
||||
|
||||
@@ -1820,7 +1820,7 @@ func (r TextPartInputParam) MarshalJSON() (data []byte, err error) {
|
||||
return apijson.MarshalRoot(r)
|
||||
}
|
||||
|
||||
func (r TextPartInputParam) implementsSessionPromptParamsPartUnion() {}
|
||||
func (r TextPartInputParam) implementsSessionChatParamsPartUnion() {}
|
||||
|
||||
type TextPartInputType string
|
||||
|
||||
@@ -2296,6 +2296,29 @@ func (r userMessageTimeJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
type SessionChatResponse struct {
|
||||
Info AssistantMessage `json:"info,required"`
|
||||
Parts []Part `json:"parts,required"`
|
||||
JSON sessionChatResponseJSON `json:"-"`
|
||||
}
|
||||
|
||||
// sessionChatResponseJSON contains the JSON metadata for the struct
|
||||
// [SessionChatResponse]
|
||||
type sessionChatResponseJSON struct {
|
||||
Info apijson.Field
|
||||
Parts apijson.Field
|
||||
raw string
|
||||
ExtraFields map[string]apijson.Field
|
||||
}
|
||||
|
||||
func (r *SessionChatResponse) UnmarshalJSON(data []byte) (err error) {
|
||||
return apijson.UnmarshalRoot(data, r)
|
||||
}
|
||||
|
||||
func (r sessionChatResponseJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
type SessionCommandResponse struct {
|
||||
Info AssistantMessage `json:"info,required"`
|
||||
Parts []Part `json:"parts,required"`
|
||||
@@ -2365,29 +2388,6 @@ func (r sessionMessagesResponseJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
type SessionPromptResponse struct {
|
||||
Info AssistantMessage `json:"info,required"`
|
||||
Parts []Part `json:"parts,required"`
|
||||
JSON sessionPromptResponseJSON `json:"-"`
|
||||
}
|
||||
|
||||
// sessionPromptResponseJSON contains the JSON metadata for the struct
|
||||
// [SessionPromptResponse]
|
||||
type sessionPromptResponseJSON struct {
|
||||
Info apijson.Field
|
||||
Parts apijson.Field
|
||||
raw string
|
||||
ExtraFields map[string]apijson.Field
|
||||
}
|
||||
|
||||
func (r *SessionPromptResponse) UnmarshalJSON(data []byte) (err error) {
|
||||
return apijson.UnmarshalRoot(data, r)
|
||||
}
|
||||
|
||||
func (r sessionPromptResponseJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
type SessionNewParams struct {
|
||||
Directory param.Field[string] `query:"directory"`
|
||||
ParentID param.Field[string] `json:"parentID"`
|
||||
@@ -2459,6 +2459,70 @@ func (r SessionAbortParams) URLQuery() (v url.Values) {
|
||||
})
|
||||
}
|
||||
|
||||
type SessionChatParams struct {
|
||||
ModelID param.Field[string] `json:"modelID,required"`
|
||||
Parts param.Field[[]SessionChatParamsPartUnion] `json:"parts,required"`
|
||||
ProviderID param.Field[string] `json:"providerID,required"`
|
||||
Directory param.Field[string] `query:"directory"`
|
||||
Agent param.Field[string] `json:"agent"`
|
||||
MessageID param.Field[string] `json:"messageID"`
|
||||
System param.Field[string] `json:"system"`
|
||||
Tools param.Field[map[string]bool] `json:"tools"`
|
||||
}
|
||||
|
||||
func (r SessionChatParams) MarshalJSON() (data []byte, err error) {
|
||||
return apijson.MarshalRoot(r)
|
||||
}
|
||||
|
||||
// URLQuery serializes [SessionChatParams]'s query parameters as `url.Values`.
|
||||
func (r SessionChatParams) URLQuery() (v url.Values) {
|
||||
return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
|
||||
ArrayFormat: apiquery.ArrayQueryFormatComma,
|
||||
NestedFormat: apiquery.NestedQueryFormatBrackets,
|
||||
})
|
||||
}
|
||||
|
||||
type SessionChatParamsPart struct {
|
||||
Type param.Field[SessionChatParamsPartsType] `json:"type,required"`
|
||||
ID param.Field[string] `json:"id"`
|
||||
Filename param.Field[string] `json:"filename"`
|
||||
Mime param.Field[string] `json:"mime"`
|
||||
Name param.Field[string] `json:"name"`
|
||||
Source param.Field[interface{}] `json:"source"`
|
||||
Synthetic param.Field[bool] `json:"synthetic"`
|
||||
Text param.Field[string] `json:"text"`
|
||||
Time param.Field[interface{}] `json:"time"`
|
||||
URL param.Field[string] `json:"url"`
|
||||
}
|
||||
|
||||
func (r SessionChatParamsPart) MarshalJSON() (data []byte, err error) {
|
||||
return apijson.MarshalRoot(r)
|
||||
}
|
||||
|
||||
func (r SessionChatParamsPart) implementsSessionChatParamsPartUnion() {}
|
||||
|
||||
// Satisfied by [TextPartInputParam], [FilePartInputParam], [AgentPartInputParam],
|
||||
// [SessionChatParamsPart].
|
||||
type SessionChatParamsPartUnion interface {
|
||||
implementsSessionChatParamsPartUnion()
|
||||
}
|
||||
|
||||
type SessionChatParamsPartsType string
|
||||
|
||||
const (
|
||||
SessionChatParamsPartsTypeText SessionChatParamsPartsType = "text"
|
||||
SessionChatParamsPartsTypeFile SessionChatParamsPartsType = "file"
|
||||
SessionChatParamsPartsTypeAgent SessionChatParamsPartsType = "agent"
|
||||
)
|
||||
|
||||
func (r SessionChatParamsPartsType) IsKnown() bool {
|
||||
switch r {
|
||||
case SessionChatParamsPartsTypeText, SessionChatParamsPartsTypeFile, SessionChatParamsPartsTypeAgent:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type SessionChildrenParams struct {
|
||||
Directory param.Field[string] `query:"directory"`
|
||||
}
|
||||
@@ -2547,78 +2611,6 @@ func (r SessionMessagesParams) URLQuery() (v url.Values) {
|
||||
})
|
||||
}
|
||||
|
||||
type SessionPromptParams struct {
|
||||
Parts param.Field[[]SessionPromptParamsPartUnion] `json:"parts,required"`
|
||||
Directory param.Field[string] `query:"directory"`
|
||||
Agent param.Field[string] `json:"agent"`
|
||||
MessageID param.Field[string] `json:"messageID"`
|
||||
Model param.Field[SessionPromptParamsModel] `json:"model"`
|
||||
System param.Field[string] `json:"system"`
|
||||
Tools param.Field[map[string]bool] `json:"tools"`
|
||||
}
|
||||
|
||||
func (r SessionPromptParams) MarshalJSON() (data []byte, err error) {
|
||||
return apijson.MarshalRoot(r)
|
||||
}
|
||||
|
||||
// URLQuery serializes [SessionPromptParams]'s query parameters as `url.Values`.
|
||||
func (r SessionPromptParams) URLQuery() (v url.Values) {
|
||||
return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
|
||||
ArrayFormat: apiquery.ArrayQueryFormatComma,
|
||||
NestedFormat: apiquery.NestedQueryFormatBrackets,
|
||||
})
|
||||
}
|
||||
|
||||
type SessionPromptParamsPart struct {
|
||||
Type param.Field[SessionPromptParamsPartsType] `json:"type,required"`
|
||||
ID param.Field[string] `json:"id"`
|
||||
Filename param.Field[string] `json:"filename"`
|
||||
Mime param.Field[string] `json:"mime"`
|
||||
Name param.Field[string] `json:"name"`
|
||||
Source param.Field[interface{}] `json:"source"`
|
||||
Synthetic param.Field[bool] `json:"synthetic"`
|
||||
Text param.Field[string] `json:"text"`
|
||||
Time param.Field[interface{}] `json:"time"`
|
||||
URL param.Field[string] `json:"url"`
|
||||
}
|
||||
|
||||
func (r SessionPromptParamsPart) MarshalJSON() (data []byte, err error) {
|
||||
return apijson.MarshalRoot(r)
|
||||
}
|
||||
|
||||
func (r SessionPromptParamsPart) implementsSessionPromptParamsPartUnion() {}
|
||||
|
||||
// Satisfied by [TextPartInputParam], [FilePartInputParam], [AgentPartInputParam],
|
||||
// [SessionPromptParamsPart].
|
||||
type SessionPromptParamsPartUnion interface {
|
||||
implementsSessionPromptParamsPartUnion()
|
||||
}
|
||||
|
||||
type SessionPromptParamsPartsType string
|
||||
|
||||
const (
|
||||
SessionPromptParamsPartsTypeText SessionPromptParamsPartsType = "text"
|
||||
SessionPromptParamsPartsTypeFile SessionPromptParamsPartsType = "file"
|
||||
SessionPromptParamsPartsTypeAgent SessionPromptParamsPartsType = "agent"
|
||||
)
|
||||
|
||||
func (r SessionPromptParamsPartsType) IsKnown() bool {
|
||||
switch r {
|
||||
case SessionPromptParamsPartsTypeText, SessionPromptParamsPartsTypeFile, SessionPromptParamsPartsTypeAgent:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type SessionPromptParamsModel struct {
|
||||
ModelID param.Field[string] `json:"modelID,required"`
|
||||
ProviderID param.Field[string] `json:"providerID,required"`
|
||||
}
|
||||
|
||||
func (r SessionPromptParamsModel) MarshalJSON() (data []byte, err error) {
|
||||
return apijson.MarshalRoot(r)
|
||||
}
|
||||
|
||||
type SessionRevertParams struct {
|
||||
MessageID param.Field[string] `json:"messageID,required"`
|
||||
Directory param.Field[string] `query:"directory"`
|
||||
|
||||
@@ -148,6 +148,52 @@ func TestSessionAbortWithOptionalParams(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionChatWithOptionalParams(t *testing.T) {
|
||||
t.Skip("Prism tests are disabled")
|
||||
baseURL := "http://localhost:4010"
|
||||
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
|
||||
baseURL = envURL
|
||||
}
|
||||
if !testutil.CheckTestServer(t, baseURL) {
|
||||
return
|
||||
}
|
||||
client := opencode.NewClient(
|
||||
option.WithBaseURL(baseURL),
|
||||
)
|
||||
_, err := client.Session.Chat(
|
||||
context.TODO(),
|
||||
"id",
|
||||
opencode.SessionChatParams{
|
||||
ModelID: opencode.F("modelID"),
|
||||
Parts: opencode.F([]opencode.SessionChatParamsPartUnion{opencode.TextPartInputParam{
|
||||
Text: opencode.F("text"),
|
||||
Type: opencode.F(opencode.TextPartInputTypeText),
|
||||
ID: opencode.F("id"),
|
||||
Synthetic: opencode.F(true),
|
||||
Time: opencode.F(opencode.TextPartInputTimeParam{
|
||||
Start: opencode.F(0.000000),
|
||||
End: opencode.F(0.000000),
|
||||
}),
|
||||
}}),
|
||||
ProviderID: opencode.F("providerID"),
|
||||
Directory: opencode.F("directory"),
|
||||
Agent: opencode.F("agent"),
|
||||
MessageID: opencode.F("msg"),
|
||||
System: opencode.F("system"),
|
||||
Tools: opencode.F(map[string]bool{
|
||||
"foo": true,
|
||||
}),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
var apierr *opencode.Error
|
||||
if errors.As(err, &apierr) {
|
||||
t.Log(string(apierr.DumpRequest(true)))
|
||||
}
|
||||
t.Fatalf("err should be nil: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionChildrenWithOptionalParams(t *testing.T) {
|
||||
t.Skip("Prism tests are disabled")
|
||||
baseURL := "http://localhost:4010"
|
||||
@@ -325,54 +371,6 @@ func TestSessionMessagesWithOptionalParams(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionPromptWithOptionalParams(t *testing.T) {
|
||||
t.Skip("Prism tests are disabled")
|
||||
baseURL := "http://localhost:4010"
|
||||
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
|
||||
baseURL = envURL
|
||||
}
|
||||
if !testutil.CheckTestServer(t, baseURL) {
|
||||
return
|
||||
}
|
||||
client := opencode.NewClient(
|
||||
option.WithBaseURL(baseURL),
|
||||
)
|
||||
_, err := client.Session.Prompt(
|
||||
context.TODO(),
|
||||
"id",
|
||||
opencode.SessionPromptParams{
|
||||
Parts: opencode.F([]opencode.SessionPromptParamsPartUnion{opencode.TextPartInputParam{
|
||||
Text: opencode.F("text"),
|
||||
Type: opencode.F(opencode.TextPartInputTypeText),
|
||||
ID: opencode.F("id"),
|
||||
Synthetic: opencode.F(true),
|
||||
Time: opencode.F(opencode.TextPartInputTimeParam{
|
||||
Start: opencode.F(0.000000),
|
||||
End: opencode.F(0.000000),
|
||||
}),
|
||||
}}),
|
||||
Directory: opencode.F("directory"),
|
||||
Agent: opencode.F("agent"),
|
||||
MessageID: opencode.F("msg"),
|
||||
Model: opencode.F(opencode.SessionPromptParamsModel{
|
||||
ModelID: opencode.F("modelID"),
|
||||
ProviderID: opencode.F("providerID"),
|
||||
}),
|
||||
System: opencode.F("system"),
|
||||
Tools: opencode.F(map[string]bool{
|
||||
"foo": true,
|
||||
}),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
var apierr *opencode.Error
|
||||
if errors.As(err, &apierr) {
|
||||
t.Log(string(apierr.DumpRequest(true)))
|
||||
}
|
||||
t.Fatalf("err should be nil: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionRevertWithOptionalParams(t *testing.T) {
|
||||
t.Skip("Prism tests are disabled")
|
||||
baseURL := "http://localhost:4010"
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
|
||||
package shared
|
||||
|
||||
type UnionBool bool
|
||||
|
||||
func (UnionBool) ImplementsConfigProviderOptionsTimeoutUnion() {}
|
||||
|
||||
type UnionInt int64
|
||||
|
||||
func (UnionInt) ImplementsConfigProviderOptionsTimeoutUnion() {}
|
||||
@@ -1,55 +0,0 @@
|
||||
import { createOpencodeClient, createOpencodeServer } from "@opencode-ai/sdk"
|
||||
|
||||
const server = await createOpencodeServer()
|
||||
const client = createOpencodeClient({ baseUrl: server.url })
|
||||
|
||||
const input = await Array.fromAsync(new Bun.Glob("packages/core/*.ts").scan())
|
||||
|
||||
const tasks: Promise<void>[] = []
|
||||
for await (const file of input) {
|
||||
console.log("processing", file)
|
||||
const session = await client.session.create()
|
||||
tasks.push(
|
||||
client.session.prompt({
|
||||
path: { id: session.data.id },
|
||||
body: {
|
||||
parts: [
|
||||
{
|
||||
type: "file",
|
||||
mime: "text/plain",
|
||||
url: `file://${file}`,
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
text: `Write tests for every public function in this file.`,
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
)
|
||||
console.log("done", file)
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
input.map(async (file) => {
|
||||
const session = await client.session.create()
|
||||
console.log("processing", file)
|
||||
await client.session.prompt({
|
||||
path: { id: session.data.id },
|
||||
body: {
|
||||
parts: [
|
||||
{
|
||||
type: "file",
|
||||
mime: "text/plain",
|
||||
url: `file://${file}`,
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
text: `Write tests for every public function in this file.`,
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
console.log("done", file)
|
||||
}),
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "0.6.0",
|
||||
"version": "0.5.29",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"typecheck": "tsc --noEmit"
|
||||
|
||||
@@ -4,8 +4,6 @@ import type { Options as ClientOptions, TDataShape, Client } from "./client/inde
|
||||
import type {
|
||||
ProjectListData,
|
||||
ProjectListResponses,
|
||||
ProjectCurrentData,
|
||||
ProjectCurrentResponses,
|
||||
EventSubscribeData,
|
||||
EventSubscribeResponses,
|
||||
ConfigGetData,
|
||||
@@ -37,8 +35,8 @@ import type {
|
||||
SessionSummarizeResponses,
|
||||
SessionMessagesData,
|
||||
SessionMessagesResponses,
|
||||
SessionPromptData,
|
||||
SessionPromptResponses,
|
||||
SessionChatData,
|
||||
SessionChatResponses,
|
||||
SessionMessageData,
|
||||
SessionMessageResponses,
|
||||
SessionCommandData,
|
||||
@@ -132,16 +130,6 @@ class Project extends _HeyApiClient {
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current project
|
||||
*/
|
||||
public current<ThrowOnError extends boolean = false>(options?: Options<ProjectCurrentData, ThrowOnError>) {
|
||||
return (options?.client ?? this._client).get<ProjectCurrentResponses, unknown, ThrowOnError>({
|
||||
url: "/project/current",
|
||||
...options,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
class Event extends _HeyApiClient {
|
||||
@@ -330,8 +318,8 @@ class Session extends _HeyApiClient {
|
||||
/**
|
||||
* Create and send a new message to a session
|
||||
*/
|
||||
public prompt<ThrowOnError extends boolean = false>(options: Options<SessionPromptData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionPromptResponses, unknown, ThrowOnError>({
|
||||
public chat<ThrowOnError extends boolean = false>(options: Options<SessionChatData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionChatResponses, unknown, ThrowOnError>({
|
||||
url: "/session/{id}/message",
|
||||
...options,
|
||||
headers: {
|
||||
|
||||
@@ -645,11 +645,7 @@ export type Config = {
|
||||
options?: {
|
||||
apiKey?: string
|
||||
baseURL?: string
|
||||
/**
|
||||
* Timeout in milliseconds for requests to this provider. Default is 300000 (5 minutes). Set to false to disable timeout.
|
||||
*/
|
||||
timeout?: number | false
|
||||
[key: string]: unknown | string | (number | false) | undefined
|
||||
[key: string]: unknown | string | undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1056,8 +1052,6 @@ export type LayoutConfig = "auto" | "stretch"
|
||||
export type Path = {
|
||||
state: string
|
||||
config: string
|
||||
worktree: string
|
||||
directory: string
|
||||
}
|
||||
|
||||
export type _Error = {
|
||||
@@ -1202,24 +1196,6 @@ export type ProjectListResponses = {
|
||||
|
||||
export type ProjectListResponse = ProjectListResponses[keyof ProjectListResponses]
|
||||
|
||||
export type ProjectCurrentData = {
|
||||
body?: never
|
||||
path?: never
|
||||
query?: {
|
||||
directory?: string
|
||||
}
|
||||
url: "/project/current"
|
||||
}
|
||||
|
||||
export type ProjectCurrentResponses = {
|
||||
/**
|
||||
* Current project
|
||||
*/
|
||||
200: Project
|
||||
}
|
||||
|
||||
export type ProjectCurrentResponse = ProjectCurrentResponses[keyof ProjectCurrentResponses]
|
||||
|
||||
export type EventSubscribeData = {
|
||||
body?: never
|
||||
path?: never
|
||||
@@ -1543,13 +1519,11 @@ export type SessionMessagesResponses = {
|
||||
|
||||
export type SessionMessagesResponse = SessionMessagesResponses[keyof SessionMessagesResponses]
|
||||
|
||||
export type SessionPromptData = {
|
||||
export type SessionChatData = {
|
||||
body?: {
|
||||
messageID?: string
|
||||
model?: {
|
||||
providerID: string
|
||||
modelID: string
|
||||
}
|
||||
providerID: string
|
||||
modelID: string
|
||||
agent?: string
|
||||
system?: string
|
||||
tools?: {
|
||||
@@ -1579,7 +1553,7 @@ export type SessionPromptData = {
|
||||
url: "/session/{id}/message"
|
||||
}
|
||||
|
||||
export type SessionPromptResponses = {
|
||||
export type SessionChatResponses = {
|
||||
/**
|
||||
* Created message
|
||||
*/
|
||||
@@ -1589,7 +1563,7 @@ export type SessionPromptResponses = {
|
||||
}
|
||||
}
|
||||
|
||||
export type SessionPromptResponse = SessionPromptResponses[keyof SessionPromptResponses]
|
||||
export type SessionChatResponse = SessionChatResponses[keyof SessionChatResponses]
|
||||
|
||||
export type SessionMessageData = {
|
||||
body?: never
|
||||
|
||||
@@ -147,7 +147,7 @@ resources:
|
||||
summarize: post /session/{id}/summarize
|
||||
message: get /session/{id}/message/{messageID}
|
||||
messages: get /session/{id}/message
|
||||
prompt: post /session/{id}/message
|
||||
chat: post /session/{id}/message
|
||||
command: post /session/{id}/command
|
||||
shell: post /session/{id}/shell
|
||||
update: patch /session/{id}
|
||||
|
||||
@@ -786,14 +786,12 @@ func (a *App) SendPrompt(ctx context.Context, prompt Prompt) (*App, tea.Cmd) {
|
||||
a.Messages = append(a.Messages, message)
|
||||
|
||||
cmds = append(cmds, func() tea.Msg {
|
||||
_, err := a.Client.Session.Prompt(ctx, a.Session.ID, opencode.SessionPromptParams{
|
||||
Model: opencode.F(opencode.SessionPromptParamsModel{
|
||||
ProviderID: opencode.F(a.Provider.ID),
|
||||
ModelID: opencode.F(a.Model.ID),
|
||||
}),
|
||||
Agent: opencode.F(a.Agent().Name),
|
||||
MessageID: opencode.F(messageID),
|
||||
Parts: opencode.F(message.ToSessionChatParams()),
|
||||
_, err := a.Client.Session.Chat(ctx, a.Session.ID, opencode.SessionChatParams{
|
||||
ProviderID: opencode.F(a.Provider.ID),
|
||||
ModelID: opencode.F(a.Model.ID),
|
||||
Agent: opencode.F(a.Agent().Name),
|
||||
MessageID: opencode.F(messageID),
|
||||
Parts: opencode.F(message.ToSessionChatParams()),
|
||||
})
|
||||
if err != nil {
|
||||
errormsg := fmt.Sprintf("failed to send message: %v", err)
|
||||
|
||||
@@ -43,9 +43,6 @@ func (p Prompt) ToMessage(
|
||||
}
|
||||
for _, att := range textAttachments {
|
||||
if source, ok := att.GetTextSource(); ok {
|
||||
if att.StartIndex > att.EndIndex || att.EndIndex > len(text) {
|
||||
continue
|
||||
}
|
||||
text = text[:att.StartIndex] + source.Value + text[att.EndIndex:]
|
||||
}
|
||||
}
|
||||
@@ -207,8 +204,8 @@ func (m Message) ToPrompt() (*Prompt, error) {
|
||||
return nil, errors.New("unknown message type")
|
||||
}
|
||||
|
||||
func (m Message) ToSessionChatParams() []opencode.SessionPromptParamsPartUnion {
|
||||
parts := []opencode.SessionPromptParamsPartUnion{}
|
||||
func (m Message) ToSessionChatParams() []opencode.SessionChatParamsPartUnion {
|
||||
parts := []opencode.SessionChatParamsPartUnion{}
|
||||
for _, part := range m.Parts {
|
||||
switch p := part.(type) {
|
||||
case opencode.TextPart:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode/web",
|
||||
"type": "module",
|
||||
"version": "0.6.0",
|
||||
"version": "0.5.29",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"dev:remote": "sst shell --stage=dev --target=Web astro dev",
|
||||
|
||||
@@ -9,7 +9,7 @@ you to use opencode at your organization.
|
||||
To get started, we recommend:
|
||||
|
||||
1. Do a trial internally with your team.
|
||||
2. [**Contact us**](mailto:contact@anoma.ly) to discuss pricing and implementation options.
|
||||
2. [**Contact us**](mailto:hello@anoma.ly) to discuss pricing and implementation options.
|
||||
|
||||
---
|
||||
|
||||
@@ -55,7 +55,7 @@ We recommend you disable this for your trial.
|
||||
## Deployment
|
||||
|
||||
Once you have completed your trial and you are ready to self-host opencode at
|
||||
your organization, you can [**contact us**](mailto:contact@anoma.ly) to discuss
|
||||
your organization, you can [**contact us**](mailto:hello@anoma.ly) to discuss
|
||||
pricing and implementation options.
|
||||
|
||||
---
|
||||
|
||||
@@ -26,7 +26,7 @@ Plugins are loaded from:
|
||||
### Basic structure
|
||||
|
||||
```js title=".opencode/plugin/example.js"
|
||||
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
|
||||
export const MyPlugin = async ({ app, client, $ }) => {
|
||||
console.log("Plugin initialized!")
|
||||
|
||||
return {
|
||||
@@ -37,9 +37,7 @@ export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
|
||||
|
||||
The plugin function receives:
|
||||
|
||||
- `project`: The current project information.
|
||||
- `directory`: The current working directory.
|
||||
- `worktree`: The git worktree path.
|
||||
- `app`: The opencode application instance.
|
||||
- `client`: An opencode SDK client for interacting with the AI.
|
||||
- `$`: Bun's [shell API](https://bun.com/docs/runtime/shell) for executing commands.
|
||||
|
||||
@@ -52,7 +50,7 @@ For TypeScript plugins, you can import types from the plugin package:
|
||||
```ts title="my-plugin.ts" {1}
|
||||
import type { Plugin } from "@opencode-ai/plugin"
|
||||
|
||||
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
|
||||
export const MyPlugin: Plugin = async ({ app, client, $ }) => {
|
||||
return {
|
||||
// Type-safe hook implementations
|
||||
}
|
||||
@@ -72,7 +70,7 @@ Here are some examples of plugins you can use to extend opencode.
|
||||
Send notifications when certain events occur:
|
||||
|
||||
```js title=".opencode/plugin/notification.js"
|
||||
export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => {
|
||||
export const NotificationPlugin = async ({ client, $ }) => {
|
||||
return {
|
||||
event: async ({ event }) => {
|
||||
// Send notification on session completion
|
||||
@@ -93,13 +91,13 @@ We are using `osascript` to run AppleScript on macOS. Here we are using it to se
|
||||
Prevent opencode from reading `.env` files:
|
||||
|
||||
```javascript title=".opencode/plugin/env-protection.js"
|
||||
export const EnvProtection = async ({ project, client, $, directory, worktree }) => {
|
||||
export const EnvProtection = async ({ client, $ }) => {
|
||||
return {
|
||||
"tool.execute.before": async (input, output) => {
|
||||
if (input.tool === "read" && output.args.filePath.includes(".env")) {
|
||||
throw new Error("Do not read .env files")
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -10,8 +10,6 @@ The opencode [JS/TS SDK](https://www.npmjs.com/package/@opencode-ai/sdk) provide
|
||||
|
||||
[Learn more](/docs/server) about how the opencode server works.
|
||||
|
||||
> **Note**: Many API endpoints now require a `directory` query parameter to specify the working directory context.
|
||||
|
||||
---
|
||||
|
||||
## Install
|
||||
@@ -67,12 +65,12 @@ server.close()
|
||||
|
||||
#### Options
|
||||
|
||||
| Option | Type | Description | Default |
|
||||
| ---------- | ------------- | ------------------------------ | ----------- |
|
||||
| `hostname` | `string` | Server hostname | `127.0.0.1` |
|
||||
| `port` | `number` | Server port | `4096` |
|
||||
| `signal` | `AbortSignal` | Abort signal for cancellation | `undefined` |
|
||||
| `timeout` | `number` | Timeout in ms for server start | `5000` |
|
||||
| Option | Type | Description | Default |
|
||||
| ---------- | -------------- | ------------------------------ | ------------- |
|
||||
| `hostname` | `string` | Server hostname | `127.0.0.1` |
|
||||
| `port` | `number` | Server port | `4096` |
|
||||
| `signal` | `AbortSignal` | Abort signal for cancellation | `undefined` |
|
||||
| `timeout` | `number` | Timeout in ms for server start | `5000` |
|
||||
|
||||
---
|
||||
|
||||
@@ -82,7 +80,7 @@ The SDK includes TypeScript definitions for all API types. Import them directly:
|
||||
|
||||
```typescript
|
||||
import type { Session, Message, Part } from "@opencode-ai/sdk"
|
||||
```
|
||||
````
|
||||
|
||||
All types are generated from the server's OpenAPI specification and available in the <a href={typesUrl}>types file</a>.
|
||||
|
||||
@@ -110,63 +108,18 @@ The SDK exposes all server APIs through a type-safe client interface.
|
||||
|
||||
### App
|
||||
|
||||
| Method | Description | Response |
|
||||
| -------------- | ------------------------- | ------------------------------------------- |
|
||||
| `app.log()` | Write a log entry | `boolean` |
|
||||
| `app.agents()` | List all available agents | <a href={typesUrl}><code>Agent[]</code></a> |
|
||||
| Method | Description | Response |
|
||||
| ------------ | ------------------ | --------------------------------------- |
|
||||
| `app.get()` | Get app info | <a href={typesUrl}><code>App</code></a> |
|
||||
| `app.init()` | Initialize the app | `boolean` |
|
||||
|
||||
---
|
||||
|
||||
#### Examples
|
||||
|
||||
```javascript
|
||||
// Log an entry
|
||||
await client.app.log({
|
||||
service: "my-app",
|
||||
level: "info",
|
||||
message: "Operation completed",
|
||||
})
|
||||
|
||||
// List available agents
|
||||
const agents = await client.app.agents()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Project
|
||||
|
||||
| Method | Description | Response |
|
||||
| ------------------- | ------------------- | --------------------------------------------- |
|
||||
| `project.list()` | List all projects | <a href={typesUrl}><code>Project[]</code></a> |
|
||||
| `project.current()` | Get current project | <a href={typesUrl}><code>Project</code></a> |
|
||||
|
||||
---
|
||||
|
||||
#### Examples
|
||||
|
||||
```javascript
|
||||
// List all projects
|
||||
const projects = await client.project.list()
|
||||
|
||||
// Get current project
|
||||
const currentProject = await client.project.current()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Path
|
||||
|
||||
| Method | Description | Response |
|
||||
| ------------ | ---------------- | ---------------------------------------- |
|
||||
| `path.get()` | Get current path | <a href={typesUrl}><code>Path</code></a> |
|
||||
|
||||
---
|
||||
|
||||
#### Examples
|
||||
|
||||
```javascript
|
||||
// Get current path information
|
||||
const pathInfo = await client.path.get()
|
||||
const app = await client.app.get()
|
||||
await client.app.init()
|
||||
```
|
||||
|
||||
---
|
||||
@@ -206,7 +159,7 @@ const { providers, default: defaults } = await client.config.providers()
|
||||
| `session.summarize({ id, providerID, modelID })` | Summarize session | Returns `boolean` |
|
||||
| `session.messages({ id })` | List messages in a session | Returns `{ info: `<a href={typesUrl}><code>Message</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}[]` |
|
||||
| `session.message({ id, messageID })` | Get message details | Returns `{ info: `<a href={typesUrl}><code>Message</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}` |
|
||||
| `session.prompt({ id, ...promptInput })` | Send prompt message | Returns <a href={typesUrl}><code>Message</code></a> |
|
||||
| `session.chat({ id, ...chatInput })` | Send chat message | Returns <a href={typesUrl}><code>Message</code></a> |
|
||||
| `session.shell({ id, agent, command })` | Run a shell command | Returns <a href={typesUrl}><code>Message</code></a> |
|
||||
| `session.revert({ id, messageID, partID? })` | Revert a message | Returns <a href={typesUrl}><code>Session</code></a> |
|
||||
| `session.unrevert({ id })` | Restore reverted messages | Returns <a href={typesUrl}><code>Session</code></a> |
|
||||
@@ -222,12 +175,10 @@ const session = await client.session.create({ title: "My session" })
|
||||
const sessions = await client.session.list()
|
||||
|
||||
// Send messages
|
||||
const message = await client.session.prompt({
|
||||
const message = await client.session.chat({
|
||||
id: session.id,
|
||||
model: {
|
||||
providerID: "anthropic",
|
||||
modelID: "claude-3-5-sonnet-20241022",
|
||||
},
|
||||
providerID: "anthropic",
|
||||
modelID: "claude-3-5-sonnet-20241022",
|
||||
parts: [{ type: "text", text: "Hello!" }],
|
||||
})
|
||||
```
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "opencode",
|
||||
"displayName": "opencode",
|
||||
"description": "opencode for VS Code",
|
||||
"version": "0.6.0",
|
||||
"version": "0.5.29",
|
||||
"publisher": "sst-dev",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
Reference in New Issue
Block a user