Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1aa4353c94 | ||
|
|
c41ada816a |
@@ -29,7 +29,7 @@
|
||||
},
|
||||
"packages/app": {
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
@@ -84,7 +84,7 @@
|
||||
},
|
||||
"packages/console/app": {
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@cloudflare/vite-plugin": "1.15.2",
|
||||
"@ibm/plex": "6.4.1",
|
||||
@@ -119,7 +119,7 @@
|
||||
},
|
||||
"packages/console/core": {
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-sts": "3.782.0",
|
||||
"@jsx-email/render": "1.1.1",
|
||||
@@ -146,7 +146,7 @@
|
||||
},
|
||||
"packages/console/function": {
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@ai-sdk/anthropic": "3.0.64",
|
||||
"@ai-sdk/openai": "3.0.48",
|
||||
@@ -168,7 +168,7 @@
|
||||
},
|
||||
"packages/console/mail": {
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
@@ -192,7 +192,7 @@
|
||||
},
|
||||
"packages/core": {
|
||||
"name": "@opencode-ai/core",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode",
|
||||
},
|
||||
@@ -253,7 +253,7 @@
|
||||
},
|
||||
"packages/desktop": {
|
||||
"name": "@opencode-ai/desktop",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"drizzle-orm": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -307,7 +307,7 @@
|
||||
},
|
||||
"packages/enterprise": {
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
@@ -337,7 +337,7 @@
|
||||
},
|
||||
"packages/function": {
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@octokit/auth-app": "8.0.1",
|
||||
"@octokit/rest": "catalog:",
|
||||
@@ -353,7 +353,7 @@
|
||||
},
|
||||
"packages/http-recorder": {
|
||||
"name": "@opencode-ai/http-recorder",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@effect/platform-node": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -366,7 +366,7 @@
|
||||
},
|
||||
"packages/llm": {
|
||||
"name": "@opencode-ai/llm",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@smithy/eventstream-codec": "4.2.14",
|
||||
"@smithy/util-utf8": "4.2.2",
|
||||
@@ -384,7 +384,7 @@
|
||||
},
|
||||
"packages/opencode": {
|
||||
"name": "opencode",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"bin": {
|
||||
"opencode": "./bin/opencode",
|
||||
},
|
||||
@@ -520,7 +520,7 @@
|
||||
},
|
||||
"packages/plugin": {
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"effect": "catalog:",
|
||||
@@ -558,7 +558,7 @@
|
||||
},
|
||||
"packages/sdk/js": {
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"cross-spawn": "catalog:",
|
||||
},
|
||||
@@ -573,7 +573,7 @@
|
||||
},
|
||||
"packages/slack": {
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"@slack/bolt": "^3.17.1",
|
||||
@@ -608,7 +608,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@kobalte/core": "catalog:",
|
||||
"@opencode-ai/core": "workspace:*",
|
||||
@@ -657,7 +657,7 @@
|
||||
},
|
||||
"packages/web": {
|
||||
"name": "@opencode-ai/web",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@astrojs/cloudflare": "12.6.3",
|
||||
"@astrojs/markdown-remark": "6.3.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/app",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
|
||||
@@ -125,7 +125,6 @@ export function applyDirectoryEvent(input: {
|
||||
const info = (event.properties as { info: Session }).info
|
||||
const result = Binary.search(input.store.session, info.id, (s) => s.id)
|
||||
if (info.time.archived) {
|
||||
if (input.store.session[result.index]!.time.archived === info.time.archived) break
|
||||
if (result.found) {
|
||||
input.setStore(
|
||||
"session",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-app",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/console-core",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-function",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/console-mail",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"dependencies": {
|
||||
"@jsx-email/all": "2.2.3",
|
||||
"@jsx-email/cli": "1.4.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"name": "@opencode-ai/core",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -157,7 +157,6 @@ export namespace Text {
|
||||
|
||||
export const Delta = EventV2.define({
|
||||
type: "session.next.text.delta",
|
||||
...options,
|
||||
schema: {
|
||||
...Base,
|
||||
delta: Schema.String,
|
||||
@@ -189,7 +188,6 @@ export namespace Reasoning {
|
||||
|
||||
export const Delta = EventV2.define({
|
||||
type: "session.next.reasoning.delta",
|
||||
...options,
|
||||
schema: {
|
||||
...Base,
|
||||
reasoningID: Schema.String,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@opencode-ai/desktop",
|
||||
"private": true,
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"homepage": "https://opencode.ai",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/enterprise",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
id = "opencode"
|
||||
name = "OpenCode"
|
||||
description = "The open source coding agent."
|
||||
version = "1.15.0"
|
||||
version = "1.14.51"
|
||||
schema_version = 1
|
||||
authors = ["Anomaly"]
|
||||
repository = "https://github.com/anomalyco/opencode"
|
||||
@@ -11,26 +11,26 @@ name = "OpenCode"
|
||||
icon = "./icons/opencode.svg"
|
||||
|
||||
[agent_servers.opencode.targets.darwin-aarch64]
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.15.0/opencode-darwin-arm64.zip"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.51/opencode-darwin-arm64.zip"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.darwin-x86_64]
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.15.0/opencode-darwin-x64.zip"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.51/opencode-darwin-x64.zip"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.linux-aarch64]
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.15.0/opencode-linux-arm64.tar.gz"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.51/opencode-linux-arm64.tar.gz"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.linux-x86_64]
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.15.0/opencode-linux-x64.tar.gz"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.51/opencode-linux-x64.tar.gz"
|
||||
cmd = "./opencode"
|
||||
args = ["acp"]
|
||||
|
||||
[agent_servers.opencode.targets.windows-x86_64]
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.15.0/opencode-windows-x64.zip"
|
||||
archive = "https://github.com/anomalyco/opencode/releases/download/v1.14.51/opencode-windows-x64.zip"
|
||||
cmd = "./opencode.exe"
|
||||
args = ["acp"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/function",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"name": "@opencode-ai/http-recorder",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"name": "@opencode-ai/llm",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"name": "opencode",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -11,7 +11,16 @@ import "@opencode-ai/core/catalog"
|
||||
import "@opencode-ai/core/session-event"
|
||||
import { Context, Effect, Layer, Option } from "effect"
|
||||
|
||||
export function toSyncDefinition<D extends EventV2.Definition>(definition: D) {
|
||||
const syncDefinitions = new WeakMap<EventV2.Definition, SyncEvent.Definition>()
|
||||
|
||||
export function toSyncDefinition<D extends EventV2.Definition>(
|
||||
definition: D,
|
||||
): SyncEvent.Definition<D["type"], D["data"], D["data"]> {
|
||||
const cached = syncDefinitions.get(definition)
|
||||
if (cached) return cached as SyncEvent.Definition<D["type"], D["data"], D["data"]>
|
||||
if (definition.version === undefined)
|
||||
throw new Error(`Event.toSyncDefinition: version required for ${definition.type}`)
|
||||
if (!definition.aggregate) throw new Error(`Event.toSyncDefinition: aggregate required for ${definition.type}`)
|
||||
const result = {
|
||||
type: definition.type,
|
||||
version: definition.version,
|
||||
@@ -19,7 +28,8 @@ export function toSyncDefinition<D extends EventV2.Definition>(definition: D) {
|
||||
schema: definition.data,
|
||||
properties: definition.data,
|
||||
}
|
||||
return result as SyncEvent.Definition<D["type"], D["data"], D["data"]>
|
||||
syncDefinitions.set(definition, result)
|
||||
return result
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, EventV2.Interface>()("@opencode/EventV2Bridge") {}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import { initProjectors } from "./projectors"
|
||||
|
||||
initProjectors()
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Config } from "@/config/config"
|
||||
import { BusEvent } from "@/bus/bus-event"
|
||||
import { SyncEvent } from "@/sync"
|
||||
import "@/event-v2-bridge"
|
||||
import "@/server/event"
|
||||
import { Schema } from "effect"
|
||||
import { HttpApi, HttpApiEndpoint, HttpApiError, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import "./init-projectors"
|
||||
|
||||
import { NodeHttpServer } from "@effect/platform-node"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { ConfigProvider, Context, Effect, Exit, Layer, Scope } from "effect"
|
||||
@@ -7,6 +5,7 @@ import { HttpRouter, HttpServer } from "effect/unstable/http"
|
||||
import { OpenApi } from "effect/unstable/httpapi"
|
||||
import { createServer } from "node:http"
|
||||
import { MDNS } from "./mdns"
|
||||
import { initProjectors } from "./projectors"
|
||||
import { HttpApiApp } from "./routes/instance/httpapi/server"
|
||||
import { disposeMiddleware } from "./routes/instance/httpapi/lifecycle"
|
||||
import { WebSocketTracker } from "./routes/instance/httpapi/websocket-tracker"
|
||||
@@ -17,6 +16,8 @@ import { lazy } from "@/util/lazy"
|
||||
// @ts-ignore This global is needed to prevent ai-sdk from logging warnings to stdout https://github.com/vercel/ai/blob/2dc67e0ef538307f21368db32d5a12345d98831b/packages/ai/src/logger/log-warnings.ts#L85
|
||||
globalThis.AI_SDK_LOG_WARNINGS = false
|
||||
|
||||
initProjectors()
|
||||
|
||||
const log = Log.create({ service: "server" })
|
||||
|
||||
export type Listener = {
|
||||
|
||||
@@ -118,9 +118,7 @@ export const layer: Layer.Layer<
|
||||
// The first project-level match wins so we don't stack AGENTS.md/CLAUDE.md from every ancestor.
|
||||
if (!Flag.OPENCODE_DISABLE_PROJECT_CONFIG) {
|
||||
for (const file of FILES) {
|
||||
const matches = yield* fs
|
||||
.findUp(file, ctx.directory, ctx.worktree)
|
||||
.pipe(Effect.catch(() => Effect.succeed([])))
|
||||
const matches = yield* fs.findUp(file, ctx.directory, ctx.worktree)
|
||||
if (matches.length > 0) {
|
||||
matches.forEach((item) => paths.add(path.resolve(item)))
|
||||
break
|
||||
|
||||
@@ -243,6 +243,13 @@ export const layer = Layer.effect(
|
||||
if (!(value.id in ctx.reasoningMap)) return
|
||||
ctx.reasoningMap[value.id].text += value.text
|
||||
if (value.providerMetadata) ctx.reasoningMap[value.id].metadata = value.providerMetadata
|
||||
if (flags.experimentalEventSystem)
|
||||
yield* events.publish(SessionEvent.Reasoning.Delta, {
|
||||
sessionID: ctx.reasoningMap[value.id].sessionID,
|
||||
reasoningID: value.id,
|
||||
delta: value.text,
|
||||
timestamp: DateTime.makeUnsafe(Date.now()),
|
||||
})
|
||||
yield* session.updatePartDelta({
|
||||
sessionID: ctx.reasoningMap[value.id].sessionID,
|
||||
messageID: ctx.reasoningMap[value.id].messageID,
|
||||
@@ -579,6 +586,12 @@ export const layer = Layer.effect(
|
||||
if (!ctx.currentText) return
|
||||
ctx.currentText.text += value.text
|
||||
if (value.providerMetadata) ctx.currentText.metadata = value.providerMetadata
|
||||
if (flags.experimentalEventSystem)
|
||||
yield* events.publish(SessionEvent.Text.Delta, {
|
||||
delta: value.text,
|
||||
sessionID: ctx.currentText.sessionID,
|
||||
timestamp: DateTime.makeUnsafe(Date.now()),
|
||||
})
|
||||
yield* session.updatePartDelta({
|
||||
sessionID: ctx.currentText.sessionID,
|
||||
messageID: ctx.currentText.messageID,
|
||||
|
||||
@@ -164,14 +164,12 @@ export default [
|
||||
SyncEvent.project(EventV2Bridge.toSyncDefinition(SessionEvent.Text.Started), (db, data, event) => {
|
||||
update(db, { id: SessionMessage.ID.make(event.id), type: "session.next.text.started", data })
|
||||
}),
|
||||
SyncEvent.project(EventV2Bridge.toSyncDefinition(SessionEvent.Text.Delta), () => {}),
|
||||
SyncEvent.project(EventV2Bridge.toSyncDefinition(SessionEvent.Text.Ended), (db, data, event) => {
|
||||
update(db, { id: SessionMessage.ID.make(event.id), type: "session.next.text.ended", data })
|
||||
}),
|
||||
SyncEvent.project(EventV2Bridge.toSyncDefinition(SessionEvent.Tool.Input.Started), (db, data, event) => {
|
||||
update(db, { id: SessionMessage.ID.make(event.id), type: "session.next.tool.input.started", data })
|
||||
}),
|
||||
SyncEvent.project(EventV2Bridge.toSyncDefinition(SessionEvent.Tool.Input.Delta), () => {}),
|
||||
SyncEvent.project(EventV2Bridge.toSyncDefinition(SessionEvent.Tool.Input.Ended), (db, data, event) => {
|
||||
update(db, { id: SessionMessage.ID.make(event.id), type: "session.next.tool.input.ended", data })
|
||||
}),
|
||||
@@ -187,7 +185,6 @@ export default [
|
||||
SyncEvent.project(EventV2Bridge.toSyncDefinition(SessionEvent.Reasoning.Started), (db, data, event) => {
|
||||
update(db, { id: SessionMessage.ID.make(event.id), type: "session.next.reasoning.started", data })
|
||||
}),
|
||||
SyncEvent.project(EventV2Bridge.toSyncDefinition(SessionEvent.Reasoning.Delta), () => {}),
|
||||
SyncEvent.project(EventV2Bridge.toSyncDefinition(SessionEvent.Reasoning.Ended), (db, data, event) => {
|
||||
update(db, { id: SessionMessage.ID.make(event.id), type: "session.next.reasoning.ended", data })
|
||||
}),
|
||||
@@ -197,7 +194,6 @@ export default [
|
||||
SyncEvent.project(EventV2Bridge.toSyncDefinition(SessionEvent.Compaction.Started), (db, data, event) => {
|
||||
update(db, { id: SessionMessage.ID.make(event.id), type: "session.next.compaction.started", data })
|
||||
}),
|
||||
SyncEvent.project(EventV2Bridge.toSyncDefinition(SessionEvent.Compaction.Delta), () => {}),
|
||||
SyncEvent.project(EventV2Bridge.toSyncDefinition(SessionEvent.Compaction.Ended), (db, data, event) => {
|
||||
update(db, { id: SessionMessage.ID.make(event.id), type: "session.next.compaction.ended", data })
|
||||
}),
|
||||
|
||||
@@ -214,7 +214,7 @@ export const defaultLayer = layer.pipe(Layer.provide(RuntimeFlags.defaultLayer))
|
||||
export const use = serviceUse(Service)
|
||||
|
||||
export const registry = new Map<string, Definition>()
|
||||
let projectors: Map<string, ProjectorFunc> | undefined
|
||||
let projectors: Map<Definition, ProjectorFunc> | undefined
|
||||
const versions = new Map<string, number>()
|
||||
let frozen = false
|
||||
let convertEvent: ConvertEvent
|
||||
@@ -226,17 +226,10 @@ export function reset() {
|
||||
}
|
||||
|
||||
export function init(input: { projectors: Array<[Definition, ProjectorFunc]>; convertEvent?: ConvertEvent }) {
|
||||
projectors = new Map(input.projectors.map(([def, func]) => [versionedType(def.type, def.version), func]))
|
||||
for (let entry of EventV2.registry.values()) {
|
||||
if (!entry.version || !entry.aggregate) continue
|
||||
register({
|
||||
type: entry.type,
|
||||
version: entry.version,
|
||||
aggregate: entry.aggregate,
|
||||
properties: entry.data,
|
||||
schema: entry.data,
|
||||
})
|
||||
for (const [def] of input.projectors) {
|
||||
register(def)
|
||||
}
|
||||
projectors = new Map(input.projectors)
|
||||
|
||||
// Install all the latest event defs to the bus. We only ever emit
|
||||
// latest versions from code, and keep around old versions for
|
||||
@@ -244,6 +237,7 @@ export function init(input: { projectors: Array<[Definition, ProjectorFunc]>; co
|
||||
// simplifies the bus to only use unversioned latest events
|
||||
for (let [type, version] of versions.entries()) {
|
||||
let def = registry.get(versionedType(type, version))!
|
||||
|
||||
BusEvent.define(def.type, def.properties)
|
||||
}
|
||||
|
||||
@@ -292,6 +286,7 @@ export function project<Def extends Definition>(
|
||||
def: Def,
|
||||
func: (db: Database.TxOrDb, data: Event<Def>["data"], event: Event<Def>) => void,
|
||||
): [Definition, ProjectorFunc] {
|
||||
register(def)
|
||||
return [def, func as ProjectorFunc]
|
||||
}
|
||||
|
||||
@@ -309,10 +304,9 @@ function process<Def extends Definition>(
|
||||
throw new Error("No projectors available. Call `SyncEvent.init` to install projectors")
|
||||
}
|
||||
|
||||
const projector = projectors.get(versionedType(def.type, def.version))
|
||||
const projector = projectors.get(def)
|
||||
if (!projector) {
|
||||
if (!def.type.includes("next")) throw new Error(`Projector not found for event: ${def.type}`)
|
||||
return
|
||||
throw new Error(`Projector not found for event: ${def.type}`)
|
||||
}
|
||||
|
||||
Database.transaction((tx) => {
|
||||
@@ -399,7 +393,7 @@ export function effectPayloads() {
|
||||
name: EffectSchema.Literal(versionedType(definition.type, definition.version!)),
|
||||
id: EffectSchema.String,
|
||||
seq: EffectSchema.Finite,
|
||||
aggregateID: EffectSchema.Literal(definition.aggregate!),
|
||||
aggregateID: EffectSchema.String,
|
||||
data: definition.data,
|
||||
}).annotate({ identifier: `SyncEvent.${definition.type}` }),
|
||||
)
|
||||
|
||||
@@ -201,8 +201,7 @@ export const layer: Layer.Layer<
|
||||
// `match` is an absolute filesystem path from `Glob.scanSync(..., { absolute: true })`.
|
||||
// Import it as `file://` so Node on Windows accepts the dynamic import.
|
||||
const mod = yield* Effect.promise(() => import(pathToFileURL(match).href))
|
||||
for (const [id, def] of Object.entries(mod)) {
|
||||
if (!isPluginTool(def)) continue
|
||||
for (const [id, def] of Object.entries<ToolDefinition>(mod)) {
|
||||
custom.push(fromPlugin(id === "default" ? namespace : `${namespace}_${id}`, def))
|
||||
}
|
||||
}
|
||||
@@ -397,10 +396,6 @@ function isZodType(value: unknown): value is z.ZodType {
|
||||
return typeof value === "object" && value !== null && "_zod" in value
|
||||
}
|
||||
|
||||
function isPluginTool(value: unknown): value is ToolDefinition {
|
||||
return typeof value === "object" && value !== null && "args" in value && "description" in value && "execute" in value
|
||||
}
|
||||
|
||||
function isJsonSchemaDefinition(value: unknown): value is JSONSchema7Definition {
|
||||
return typeof value === "boolean" || (typeof value === "object" && value !== null && !Array.isArray(value))
|
||||
}
|
||||
|
||||
@@ -158,33 +158,6 @@ describe("tool.registry", () => {
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("ignores non-tool exports in .opencode/tool files", () =>
|
||||
Effect.gen(function* () {
|
||||
const test = yield* TestInstance
|
||||
const tool = path.join(test.directory, ".opencode", "tool")
|
||||
yield* Effect.promise(() => fs.mkdir(tool, { recursive: true }))
|
||||
yield* Effect.promise(() =>
|
||||
Bun.write(
|
||||
path.join(tool, "mixed.ts"),
|
||||
[
|
||||
"export const helper = 'not a tool'",
|
||||
"export default {",
|
||||
" description: 'mixed tool',",
|
||||
" args: {},",
|
||||
" execute: async () => 'ok',",
|
||||
"}",
|
||||
"",
|
||||
].join("\n"),
|
||||
),
|
||||
)
|
||||
|
||||
const registry = yield* ToolRegistry.Service
|
||||
const ids = yield* registry.ids()
|
||||
expect(ids).toContain("mixed")
|
||||
expect(ids).not.toContain("mixed_helper")
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("loads tools from .opencode/tools (plural)", () =>
|
||||
Effect.gen(function* () {
|
||||
const test = yield* TestInstance
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/plugin",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -42,13 +42,9 @@ export type Event =
|
||||
| EventPtyDeleted
|
||||
| EventInstallationUpdated
|
||||
| EventInstallationUpdateAvailable
|
||||
| EventMessageUpdated
|
||||
| EventMessageRemoved
|
||||
| EventMessagePartUpdated
|
||||
| EventMessagePartRemoved
|
||||
| EventSessionCreated
|
||||
| EventSessionUpdated
|
||||
| EventSessionDeleted
|
||||
| EventServerConnected
|
||||
| EventGlobalDisposed
|
||||
| EventCatalogModelUpdated
|
||||
| EventSessionNextAgentSwitched
|
||||
| EventSessionNextModelSwitched
|
||||
| EventSessionNextPrompted
|
||||
@@ -75,9 +71,6 @@ export type Event =
|
||||
| EventSessionNextCompactionStarted
|
||||
| EventSessionNextCompactionDelta
|
||||
| EventSessionNextCompactionEnded
|
||||
| EventServerConnected
|
||||
| EventGlobalDisposed
|
||||
| EventCatalogModelUpdated
|
||||
|
||||
export type OAuth = {
|
||||
type: "oauth"
|
||||
@@ -370,6 +363,13 @@ export type Pty = {
|
||||
pid: number
|
||||
}
|
||||
|
||||
export type Prompt = {
|
||||
text: string
|
||||
files?: Array<PromptFileAttachment>
|
||||
agents?: Array<PromptAgentAttachment>
|
||||
references?: Array<PromptReferenceAttachment>
|
||||
}
|
||||
|
||||
export type OutputFormatText = {
|
||||
type: "text"
|
||||
}
|
||||
@@ -778,13 +778,6 @@ export type Session = {
|
||||
}
|
||||
}
|
||||
|
||||
export type Prompt = {
|
||||
text: string
|
||||
files?: Array<PromptFileAttachment>
|
||||
agents?: Array<PromptAgentAttachment>
|
||||
references?: Array<PromptReferenceAttachment>
|
||||
}
|
||||
|
||||
export type GlobalEvent = {
|
||||
directory: string
|
||||
project?: string
|
||||
@@ -827,13 +820,9 @@ export type GlobalEvent = {
|
||||
| EventPtyDeleted
|
||||
| EventInstallationUpdated
|
||||
| EventInstallationUpdateAvailable
|
||||
| EventMessageUpdated
|
||||
| EventMessageRemoved
|
||||
| EventMessagePartUpdated
|
||||
| EventMessagePartRemoved
|
||||
| EventSessionCreated
|
||||
| EventSessionUpdated
|
||||
| EventSessionDeleted
|
||||
| EventServerConnected
|
||||
| EventGlobalDisposed
|
||||
| EventCatalogModelUpdated
|
||||
| EventSessionNextAgentSwitched
|
||||
| EventSessionNextModelSwitched
|
||||
| EventSessionNextPrompted
|
||||
@@ -860,9 +849,6 @@ export type GlobalEvent = {
|
||||
| EventSessionNextCompactionStarted
|
||||
| EventSessionNextCompactionDelta
|
||||
| EventSessionNextCompactionEnded
|
||||
| EventServerConnected
|
||||
| EventGlobalDisposed
|
||||
| EventCatalogModelUpdated
|
||||
| SyncEventMessageUpdated
|
||||
| SyncEventMessageRemoved
|
||||
| SyncEventMessagePartUpdated
|
||||
@@ -882,20 +868,20 @@ export type GlobalEvent = {
|
||||
| SyncEventSessionNextTextStarted
|
||||
| SyncEventSessionNextTextDelta
|
||||
| SyncEventSessionNextTextEnded
|
||||
| SyncEventSessionNextReasoningStarted
|
||||
| SyncEventSessionNextReasoningDelta
|
||||
| SyncEventSessionNextReasoningEnded
|
||||
| SyncEventSessionNextToolInputStarted
|
||||
| SyncEventSessionNextToolInputDelta
|
||||
| SyncEventSessionNextToolInputEnded
|
||||
| SyncEventSessionNextToolCalled
|
||||
| SyncEventSessionNextToolProgress
|
||||
| SyncEventSessionNextToolSuccess
|
||||
| SyncEventSessionNextToolFailed
|
||||
| SyncEventSessionNextReasoningStarted
|
||||
| SyncEventSessionNextReasoningDelta
|
||||
| SyncEventSessionNextReasoningEnded
|
||||
| SyncEventSessionNextRetried
|
||||
| SyncEventSessionNextCompactionStarted
|
||||
| SyncEventSessionNextCompactionDelta
|
||||
| SyncEventSessionNextCompactionEnded
|
||||
| SyncEventSessionNextToolProgress
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2183,47 +2169,6 @@ export type SyncEventSessionNextTextEnded = {
|
||||
}
|
||||
}
|
||||
|
||||
export type SyncEventSessionNextReasoningStarted = {
|
||||
type: "sync"
|
||||
name: "session.next.reasoning.started.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: {
|
||||
timestamp: number
|
||||
sessionID: string
|
||||
reasoningID: string
|
||||
}
|
||||
}
|
||||
|
||||
export type SyncEventSessionNextReasoningDelta = {
|
||||
type: "sync"
|
||||
name: "session.next.reasoning.delta.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: {
|
||||
timestamp: number
|
||||
sessionID: string
|
||||
reasoningID: string
|
||||
delta: string
|
||||
}
|
||||
}
|
||||
|
||||
export type SyncEventSessionNextReasoningEnded = {
|
||||
type: "sync"
|
||||
name: "session.next.reasoning.ended.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: {
|
||||
timestamp: number
|
||||
sessionID: string
|
||||
reasoningID: string
|
||||
text: string
|
||||
}
|
||||
}
|
||||
|
||||
export type SyncEventSessionNextToolInputStarted = {
|
||||
type: "sync"
|
||||
name: "session.next.tool.input.started.1"
|
||||
@@ -2289,23 +2234,6 @@ export type SyncEventSessionNextToolCalled = {
|
||||
}
|
||||
}
|
||||
|
||||
export type SyncEventSessionNextToolProgress = {
|
||||
type: "sync"
|
||||
name: "session.next.tool.progress.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: {
|
||||
timestamp: number
|
||||
sessionID: string
|
||||
callID: string
|
||||
structured: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
content: Array<ToolTextContent | ToolFileContent>
|
||||
}
|
||||
}
|
||||
|
||||
export type SyncEventSessionNextToolSuccess = {
|
||||
type: "sync"
|
||||
name: "session.next.tool.success.1"
|
||||
@@ -2349,6 +2277,47 @@ export type SyncEventSessionNextToolFailed = {
|
||||
}
|
||||
}
|
||||
|
||||
export type SyncEventSessionNextReasoningStarted = {
|
||||
type: "sync"
|
||||
name: "session.next.reasoning.started.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: {
|
||||
timestamp: number
|
||||
sessionID: string
|
||||
reasoningID: string
|
||||
}
|
||||
}
|
||||
|
||||
export type SyncEventSessionNextReasoningDelta = {
|
||||
type: "sync"
|
||||
name: "session.next.reasoning.delta.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: {
|
||||
timestamp: number
|
||||
sessionID: string
|
||||
reasoningID: string
|
||||
delta: string
|
||||
}
|
||||
}
|
||||
|
||||
export type SyncEventSessionNextReasoningEnded = {
|
||||
type: "sync"
|
||||
name: "session.next.reasoning.ended.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: "sessionID"
|
||||
data: {
|
||||
timestamp: number
|
||||
sessionID: string
|
||||
reasoningID: string
|
||||
text: string
|
||||
}
|
||||
}
|
||||
|
||||
export type SyncEventSessionNextRetried = {
|
||||
type: "sync"
|
||||
name: "session.next.retried.1"
|
||||
@@ -2403,6 +2372,23 @@ export type SyncEventSessionNextCompactionEnded = {
|
||||
}
|
||||
}
|
||||
|
||||
export type SyncEventSessionNextToolProgress = {
|
||||
type: "sync"
|
||||
name: "session.next.tool.progress.1"
|
||||
id: string
|
||||
seq: number
|
||||
aggregateID: string
|
||||
data: {
|
||||
timestamp: number
|
||||
sessionID: string
|
||||
callID: string
|
||||
structured: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
content: Array<ToolTextContent | ToolFileContent>
|
||||
}
|
||||
}
|
||||
|
||||
export type EventServerInstanceDisposed = {
|
||||
id: string
|
||||
type: "server.instance.disposed"
|
||||
@@ -2683,68 +2669,125 @@ export type EventInstallationUpdateAvailable = {
|
||||
}
|
||||
}
|
||||
|
||||
export type EventMessageUpdated = {
|
||||
export type EventServerConnected = {
|
||||
id: string
|
||||
type: "message.updated"
|
||||
type: "server.connected"
|
||||
properties: {
|
||||
sessionID: string
|
||||
info: Message
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
|
||||
export type EventMessageRemoved = {
|
||||
export type EventGlobalDisposed = {
|
||||
id: string
|
||||
type: "message.removed"
|
||||
type: "global.disposed"
|
||||
properties: {
|
||||
sessionID: string
|
||||
messageID: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
|
||||
export type EventMessagePartUpdated = {
|
||||
export type ModelV2Info = {
|
||||
id: string
|
||||
type: "message.part.updated"
|
||||
properties: {
|
||||
sessionID: string
|
||||
part: Part
|
||||
time: number
|
||||
apiID: string
|
||||
providerID: string
|
||||
family?: string
|
||||
name: string
|
||||
endpoint:
|
||||
| {
|
||||
type: "unknown"
|
||||
}
|
||||
| {
|
||||
type: "openai/responses"
|
||||
url: string
|
||||
websocket?: boolean
|
||||
}
|
||||
| {
|
||||
type: "openai/completions"
|
||||
url: string
|
||||
reasoning?:
|
||||
| {
|
||||
type: "reasoning_content"
|
||||
}
|
||||
| {
|
||||
type: "reasoning_details"
|
||||
}
|
||||
}
|
||||
| {
|
||||
type: "anthropic/messages"
|
||||
url: string
|
||||
}
|
||||
| {
|
||||
type: "aisdk"
|
||||
package: string
|
||||
url?: string
|
||||
}
|
||||
capabilities: {
|
||||
tools: boolean
|
||||
input: Array<string>
|
||||
output: Array<string>
|
||||
}
|
||||
options: {
|
||||
headers: {
|
||||
[key: string]: string
|
||||
}
|
||||
body: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
aisdk: {
|
||||
provider: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
request: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
variant?: string
|
||||
}
|
||||
variants: Array<{
|
||||
id: string
|
||||
headers: {
|
||||
[key: string]: string
|
||||
}
|
||||
body: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
aisdk: {
|
||||
provider: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
request: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
}>
|
||||
time: {
|
||||
released: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN"
|
||||
}
|
||||
cost: Array<{
|
||||
tier?: {
|
||||
type: "context"
|
||||
size: number
|
||||
}
|
||||
input: number
|
||||
output: number
|
||||
cache: {
|
||||
read: number
|
||||
write: number
|
||||
}
|
||||
}>
|
||||
status: "alpha" | "beta" | "deprecated" | "active"
|
||||
enabled: boolean
|
||||
limit: {
|
||||
context: number
|
||||
input?: number
|
||||
output: number
|
||||
}
|
||||
}
|
||||
|
||||
export type EventMessagePartRemoved = {
|
||||
export type EventCatalogModelUpdated = {
|
||||
id: string
|
||||
type: "message.part.removed"
|
||||
type: "catalog.model.updated"
|
||||
properties: {
|
||||
sessionID: string
|
||||
messageID: string
|
||||
partID: string
|
||||
}
|
||||
}
|
||||
|
||||
export type EventSessionCreated = {
|
||||
id: string
|
||||
type: "session.created"
|
||||
properties: {
|
||||
sessionID: string
|
||||
info: Session
|
||||
}
|
||||
}
|
||||
|
||||
export type EventSessionUpdated = {
|
||||
id: string
|
||||
type: "session.updated"
|
||||
properties: {
|
||||
sessionID: string
|
||||
info: Session
|
||||
}
|
||||
}
|
||||
|
||||
export type EventSessionDeleted = {
|
||||
id: string
|
||||
type: "session.deleted"
|
||||
properties: {
|
||||
sessionID: string
|
||||
info: Session
|
||||
model: ModelV2Info
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3129,128 +3172,6 @@ export type EventSessionNextCompactionEnded = {
|
||||
}
|
||||
}
|
||||
|
||||
export type EventServerConnected = {
|
||||
id: string
|
||||
type: "server.connected"
|
||||
properties: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
|
||||
export type EventGlobalDisposed = {
|
||||
id: string
|
||||
type: "global.disposed"
|
||||
properties: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
|
||||
export type ModelV2Info = {
|
||||
id: string
|
||||
apiID: string
|
||||
providerID: string
|
||||
family?: string
|
||||
name: string
|
||||
endpoint:
|
||||
| {
|
||||
type: "unknown"
|
||||
}
|
||||
| {
|
||||
type: "openai/responses"
|
||||
url: string
|
||||
websocket?: boolean
|
||||
}
|
||||
| {
|
||||
type: "openai/completions"
|
||||
url: string
|
||||
reasoning?:
|
||||
| {
|
||||
type: "reasoning_content"
|
||||
}
|
||||
| {
|
||||
type: "reasoning_details"
|
||||
}
|
||||
}
|
||||
| {
|
||||
type: "anthropic/messages"
|
||||
url: string
|
||||
}
|
||||
| {
|
||||
type: "aisdk"
|
||||
package: string
|
||||
url?: string
|
||||
}
|
||||
capabilities: {
|
||||
tools: boolean
|
||||
input: Array<string>
|
||||
output: Array<string>
|
||||
}
|
||||
options: {
|
||||
headers: {
|
||||
[key: string]: string
|
||||
}
|
||||
body: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
aisdk: {
|
||||
provider: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
request: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
variant?: string
|
||||
}
|
||||
variants: Array<{
|
||||
id: string
|
||||
headers: {
|
||||
[key: string]: string
|
||||
}
|
||||
body: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
aisdk: {
|
||||
provider: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
request: {
|
||||
[key: string]: unknown
|
||||
}
|
||||
}
|
||||
}>
|
||||
time: {
|
||||
released: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN"
|
||||
}
|
||||
cost: Array<{
|
||||
tier?: {
|
||||
type: "context"
|
||||
size: number
|
||||
}
|
||||
input: number
|
||||
output: number
|
||||
cache: {
|
||||
read: number
|
||||
write: number
|
||||
}
|
||||
}>
|
||||
status: "alpha" | "beta" | "deprecated" | "active"
|
||||
enabled: boolean
|
||||
limit: {
|
||||
context: number
|
||||
input?: number
|
||||
output: number
|
||||
}
|
||||
}
|
||||
|
||||
export type EventCatalogModelUpdated = {
|
||||
id: string
|
||||
type: "catalog.model.updated"
|
||||
properties: {
|
||||
model: ModelV2Info
|
||||
}
|
||||
}
|
||||
|
||||
export type SessionInfo = {
|
||||
id: string
|
||||
parentID?: string
|
||||
|
||||
+547
-952
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/slack",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@opencode-ai/ui",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@opencode-ai/web",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"dev:remote": "VITE_API_URL=https://api.opencode.ai astro dev",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "opencode",
|
||||
"displayName": "opencode",
|
||||
"description": "opencode for VS Code",
|
||||
"version": "1.15.0",
|
||||
"version": "1.14.51",
|
||||
"publisher": "sst-dev",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
Reference in New Issue
Block a user