enterprise (#4617)

Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com>
This commit is contained in:
Dax
2025-11-21 20:41:27 -05:00
committed by GitHub
parent 76192fbced
commit 49408c00e9
1205 changed files with 3057 additions and 1491 deletions

View File

@@ -0,0 +1,148 @@
import { Bus } from "@/bus"
import { Config } from "@/config/config"
import { Session } from "@/session"
import { MessageV2 } from "@/session/message-v2"
import { Storage } from "@/storage/storage"
import { Log } from "@/util/log"
import type * as SDK from "@opencode-ai/sdk"
export namespace ShareNext {
const log = Log.create({ service: "share-next" })
export async function init() {
const config = await Config.get()
if (!config.enterprise) return
Bus.subscribe(Session.Event.Updated, async (evt) => {
await sync(evt.properties.info.id, [
{
type: "session",
data: evt.properties.info,
},
])
})
Bus.subscribe(MessageV2.Event.Updated, async (evt) => {
await sync(evt.properties.info.sessionID, [
{
type: "message",
data: evt.properties.info,
},
])
})
Bus.subscribe(MessageV2.Event.PartUpdated, async (evt) => {
await sync(evt.properties.part.sessionID, [
{
type: "part",
data: evt.properties.part,
},
])
})
Bus.subscribe(Session.Event.Diff, async (evt) => {
await sync(evt.properties.sessionID, [
{
type: "session_diff",
data: evt.properties.diff,
},
])
})
}
export async function create(sessionID: string) {
log.info("creating share", { sessionID })
const url = await Config.get().then((x) => x.enterprise!.url)
const result = await fetch(`${url}/api/share`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ sessionID: sessionID }),
})
.then((x) => x.json())
.then((x) => x as { url: string; secret: string })
await Storage.write(["session_share", sessionID], {
id: sessionID,
...result,
})
fullSync(sessionID)
return result
}
function get(sessionID: string) {
return Storage.read<{
id: string
secret: string
url: string
}>(["session_share", sessionID])
}
type Data =
| {
type: "session"
data: SDK.Session
}
| {
type: "message"
data: SDK.Message
}
| {
type: "part"
data: SDK.Part
}
| {
type: "session_diff"
data: SDK.FileDiff[]
}
async function sync(sessionID: string, data: Data[]) {
const url = await Config.get().then((x) => x.enterprise!.url)
const share = await get(sessionID)
if (!share) return
await fetch(`${url}/api/share/${share.id}/sync`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
secret: share.secret,
data,
}),
})
}
export async function remove(sessionID: string) {
log.info("removing share", { sessionID })
const url = await Config.get().then((x) => x.enterprise!.url)
const share = await get(sessionID)
if (!share) return
await fetch(`${url}/api/share/${share.id}`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
secret: share.secret,
}),
})
await Storage.remove(["session_share", share.id])
}
async function fullSync(sessionID: string) {
log.info("full sync", { sessionID })
const session = await Session.get(sessionID)
const diffs = await Session.diff(sessionID)
const messages = await Array.fromAsync(MessageV2.stream(sessionID))
await sync(sessionID, [
{
type: "session",
data: session,
},
...messages.map((x) => ({
type: "message" as const,
data: x.info,
})),
...messages.flatMap((x) => x.parts.map((y) => ({ type: "part" as const, data: y }))),
{
type: "session_diff",
data: diffs,
},
])
}
}