Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
Kit Langton
40ca8a6fc4 feat: unwrap share namespaces to flat exports + barrel 2026-04-15 23:14:55 -04:00
10 changed files with 361 additions and 363 deletions

View file

@ -21,7 +21,7 @@ import { cmd } from "./cmd"
import { ModelsDev } from "../../provider/models" import { ModelsDev } from "../../provider/models"
import { Instance } from "@/project/instance" import { Instance } from "@/project/instance"
import { bootstrap } from "../bootstrap" import { bootstrap } from "../bootstrap"
import { SessionShare } from "@/share/session" import { SessionShare } from "@/share"
import { Session } from "../../session" import { Session } from "../../session"
import type { SessionID } from "../../session/schema" import type { SessionID } from "../../session/schema"
import { MessageID, PartID } from "../../session/schema" import { MessageID, PartID } from "../../session/schema"

View file

@ -7,7 +7,7 @@ import { bootstrap } from "../bootstrap"
import { Database } from "../../storage/db" import { Database } from "../../storage/db"
import { SessionTable, MessageTable, PartTable } from "../../session/session.sql" import { SessionTable, MessageTable, PartTable } from "../../session/session.sql"
import { Instance } from "../../project/instance" import { Instance } from "../../project/instance"
import { ShareNext } from "../../share/share-next" import { ShareNext } from "../../share"
import { EOL } from "os" import { EOL } from "os"
import { Filesystem } from "../../util/filesystem" import { Filesystem } from "../../util/filesystem"
import { AppRuntime } from "@/effect/app-runtime" import { AppRuntime } from "@/effect/app-runtime"

View file

@ -45,8 +45,8 @@ import { Vcs } from "@/project/vcs"
import { Worktree } from "@/worktree" import { Worktree } from "@/worktree"
import { Pty } from "@/pty" import { Pty } from "@/pty"
import { Installation } from "@/installation" import { Installation } from "@/installation"
import { ShareNext } from "@/share/share-next" import { ShareNext } from "@/share"
import { SessionShare } from "@/share/session" import { SessionShare } from "@/share"
export const AppLayer = Layer.mergeAll( export const AppLayer = Layer.mergeAll(
AppFileSystem.defaultLayer, AppFileSystem.defaultLayer,

View file

@ -5,7 +5,7 @@ import { Plugin } from "@/plugin"
import { LSP } from "@/lsp" import { LSP } from "@/lsp"
import { FileWatcher } from "@/file/watcher" import { FileWatcher } from "@/file/watcher"
import { Format } from "@/format" import { Format } from "@/format"
import { ShareNext } from "@/share/share-next" import { ShareNext } from "@/share"
import { File } from "@/file" import { File } from "@/file"
import { Vcs } from "@/project/vcs" import { Vcs } from "@/project/vcs"
import { Snapshot } from "@/snapshot" import { Snapshot } from "@/snapshot"

View file

@ -10,7 +10,7 @@ import { Command } from "../command"
import { Instance } from "./instance" import { Instance } from "./instance"
import { Log } from "@/util/log" import { Log } from "@/util/log"
import { FileWatcher } from "@/file/watcher" import { FileWatcher } from "@/file/watcher"
import { ShareNext } from "@/share/share-next" import { ShareNext } from "@/share"
import * as Effect from "effect/Effect" import * as Effect from "effect/Effect"
export const InstanceBootstrap = Effect.gen(function* () { export const InstanceBootstrap = Effect.gen(function* () {

View file

@ -9,7 +9,7 @@ import { SessionPrompt } from "../../session/prompt"
import { SessionRunState } from "@/session/run-state" import { SessionRunState } from "@/session/run-state"
import { SessionCompaction } from "../../session/compaction" import { SessionCompaction } from "../../session/compaction"
import { SessionRevert } from "../../session/revert" import { SessionRevert } from "../../session/revert"
import { SessionShare } from "@/share/session" import { SessionShare } from "@/share"
import { SessionStatus } from "@/session/status" import { SessionStatus } from "@/session/status"
import { SessionSummary } from "@/session/summary" import { SessionSummary } from "@/session/summary"
import { Todo } from "../../session/todo" import { Todo } from "../../session/todo"

View file

@ -0,0 +1,2 @@
export * as ShareNext from "./share-next"
export * as SessionShare from "./session"

View file

@ -4,18 +4,17 @@ import { SyncEvent } from "@/sync"
import { Effect, Layer, Scope, Context } from "effect" import { Effect, Layer, Scope, Context } from "effect"
import { Config } from "../config" import { Config } from "../config"
import { Flag } from "../flag/flag" import { Flag } from "../flag/flag"
import { ShareNext } from "./share-next" import { ShareNext } from "."
export namespace SessionShare { export interface Interface {
export interface Interface {
readonly create: (input?: Session.CreateInput) => Effect.Effect<Session.Info> readonly create: (input?: Session.CreateInput) => Effect.Effect<Session.Info>
readonly share: (sessionID: SessionID) => Effect.Effect<{ url: string }, unknown> readonly share: (sessionID: SessionID) => Effect.Effect<{ url: string }, unknown>
readonly unshare: (sessionID: SessionID) => Effect.Effect<void, unknown> readonly unshare: (sessionID: SessionID) => Effect.Effect<void, unknown>
} }
export class Service extends Context.Service<Service, Interface>()("@opencode/SessionShare") {} export class Service extends Context.Service<Service, Interface>()("@opencode/SessionShare") {}
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
Effect.gen(function* () { Effect.gen(function* () {
const cfg = yield* Config.Service const cfg = yield* Config.Service
@ -49,11 +48,10 @@ export namespace SessionShare {
return Service.of({ create, share, unshare }) return Service.of({ create, share, unshare })
}), }),
) )
export const defaultLayer = layer.pipe( export const defaultLayer = layer.pipe(
Layer.provide(ShareNext.defaultLayer), Layer.provide(ShareNext.defaultLayer),
Layer.provide(Session.defaultLayer), Layer.provide(Session.defaultLayer),
Layer.provide(Config.defaultLayer), Layer.provide(Config.defaultLayer),
) )
}

View file

@ -14,36 +14,35 @@ import { Config } from "@/config"
import { Log } from "@/util/log" import { Log } from "@/util/log"
import { SessionShareTable } from "./share.sql" import { SessionShareTable } from "./share.sql"
export namespace ShareNext { const log = Log.create({ service: "share-next" })
const log = Log.create({ service: "share-next" }) const disabled = process.env["OPENCODE_DISABLE_SHARE"] === "true" || process.env["OPENCODE_DISABLE_SHARE"] === "1"
const disabled = process.env["OPENCODE_DISABLE_SHARE"] === "true" || process.env["OPENCODE_DISABLE_SHARE"] === "1"
export type Api = { export type Api = {
create: string create: string
sync: (shareID: string) => string sync: (shareID: string) => string
remove: (shareID: string) => string remove: (shareID: string) => string
data: (shareID: string) => string data: (shareID: string) => string
} }
export type Req = { export type Req = {
headers: Record<string, string> headers: Record<string, string>
api: Api api: Api
baseUrl: string baseUrl: string
} }
const ShareSchema = Schema.Struct({ const ShareSchema = Schema.Struct({
id: Schema.String, id: Schema.String,
url: Schema.String, url: Schema.String,
secret: Schema.String, secret: Schema.String,
}) })
export type Share = typeof ShareSchema.Type export type Share = typeof ShareSchema.Type
type State = { type State = {
queue: Map<string, { data: Map<string, Data> }> queue: Map<string, { data: Map<string, Data> }>
scope: Scope.Closeable scope: Scope.Closeable
} }
type Data = type Data =
| { | {
type: "session" type: "session"
data: SDK.Session data: SDK.Session
@ -65,32 +64,32 @@ export namespace ShareNext {
data: SDK.Model[] data: SDK.Model[]
} }
export interface Interface { export interface Interface {
readonly init: () => Effect.Effect<void, unknown> readonly init: () => Effect.Effect<void, unknown>
readonly url: () => Effect.Effect<string, unknown> readonly url: () => Effect.Effect<string, unknown>
readonly request: () => Effect.Effect<Req, unknown> readonly request: () => Effect.Effect<Req, unknown>
readonly create: (sessionID: SessionID) => Effect.Effect<Share, unknown> readonly create: (sessionID: SessionID) => Effect.Effect<Share, unknown>
readonly remove: (sessionID: SessionID) => Effect.Effect<void, unknown> readonly remove: (sessionID: SessionID) => Effect.Effect<void, unknown>
} }
export class Service extends Context.Service<Service, Interface>()("@opencode/ShareNext") {} export class Service extends Context.Service<Service, Interface>()("@opencode/ShareNext") {}
const db = <T>(fn: (d: Parameters<typeof Database.use>[0] extends (trx: infer D) => any ? D : never) => T) => const db = <T>(fn: (d: Parameters<typeof Database.use>[0] extends (trx: infer D) => any ? D : never) => T) =>
Effect.sync(() => Database.use(fn)) Effect.sync(() => Database.use(fn))
function api(resource: string): Api { function api(resource: string): Api {
return { return {
create: `/api/${resource}`, create: `/api/${resource}`,
sync: (shareID) => `/api/${resource}/${shareID}/sync`, sync: (shareID) => `/api/${resource}/${shareID}/sync`,
remove: (shareID) => `/api/${resource}/${shareID}`, remove: (shareID) => `/api/${resource}/${shareID}`,
data: (shareID) => `/api/${resource}/${shareID}/data`, data: (shareID) => `/api/${resource}/${shareID}/data`,
} }
} }
const legacyApi = api("share") const legacyApi = api("share")
const consoleApi = api("shares") const consoleApi = api("shares")
function key(item: Data) { function key(item: Data) {
switch (item.type) { switch (item.type) {
case "session": case "session":
return "session" return "session"
@ -103,9 +102,9 @@ export namespace ShareNext {
case "model": case "model":
return "model" return "model"
} }
} }
export const layer = Layer.effect( export const layer = Layer.effect(
Service, Service,
Effect.gen(function* () { Effect.gen(function* () {
const account = yield* Account.Service const account = yield* Account.Service
@ -337,14 +336,13 @@ export namespace ShareNext {
return Service.of({ init, url, request, create, remove }) return Service.of({ init, url, request, create, remove })
}), }),
) )
export const defaultLayer = layer.pipe( export const defaultLayer = layer.pipe(
Layer.provide(Bus.layer), Layer.provide(Bus.layer),
Layer.provide(Account.defaultLayer), Layer.provide(Account.defaultLayer),
Layer.provide(Config.defaultLayer), Layer.provide(Config.defaultLayer),
Layer.provide(FetchHttpClient.layer), Layer.provide(FetchHttpClient.layer),
Layer.provide(Provider.defaultLayer), Layer.provide(Provider.defaultLayer),
Layer.provide(Session.defaultLayer), Layer.provide(Session.defaultLayer),
) )
}

View file

@ -12,7 +12,7 @@ import { Config } from "../../src/config"
import { Provider } from "../../src/provider" import { Provider } from "../../src/provider"
import { Session } from "../../src/session" import { Session } from "../../src/session"
import type { SessionID } from "../../src/session/schema" import type { SessionID } from "../../src/session/schema"
import { ShareNext } from "../../src/share/share-next" import { ShareNext } from "../../src/share"
import { SessionShareTable } from "../../src/share/share.sql" import { SessionShareTable } from "../../src/share/share.sql"
import { Database, eq } from "../../src/storage/db" import { Database, eq } from "../../src/storage/db"
import { provideTmpdirInstance } from "../fixture/fixture" import { provideTmpdirInstance } from "../fixture/fixture"