diff options
| author | Dax Raad <[email protected]> | 2025-11-24 22:58:47 -0500 |
|---|---|---|
| committer | Dax Raad <[email protected]> | 2025-11-24 22:58:47 -0500 |
| commit | 69d1381ba334037cc57eef483c1b23b58b0f314e (patch) | |
| tree | a0514664e068cc43af0b39a4878c50427a313334 /packages/enterprise/src | |
| parent | ccec8c479248fdaefaaf9ad9606bfc4eecb042c9 (diff) | |
| download | opencode-69d1381ba334037cc57eef483c1b23b58b0f314e.tar.gz opencode-69d1381ba334037cc57eef483c1b23b58b0f314e.zip | |
core: refactor share system to separate session IDs from share IDs
- Generate shorter share IDs from session IDs for better URL structure
- Update API routes to use shareID parameter instead of sessionID
- Improve sync mechanism with better data queuing and deduplication
- Maintain backward compatibility while improving security and organization
Diffstat (limited to 'packages/enterprise/src')
| -rw-r--r-- | packages/enterprise/src/core/share.ts | 23 | ||||
| -rw-r--r-- | packages/enterprise/src/core/storage.ts | 1 | ||||
| -rw-r--r-- | packages/enterprise/src/routes/api/[...path].ts | 28 | ||||
| -rw-r--r-- | packages/enterprise/src/routes/share/[shareID].tsx (renamed from packages/enterprise/src/routes/share/[sessionID].tsx) | 46 |
4 files changed, 48 insertions, 50 deletions
diff --git a/packages/enterprise/src/core/share.ts b/packages/enterprise/src/core/share.ts index c24077ec3..dff7d0d74 100644 --- a/packages/enterprise/src/core/share.ts +++ b/packages/enterprise/src/core/share.ts @@ -8,6 +8,7 @@ export namespace Share { export const Info = z.object({ id: z.string(), secret: z.string(), + sessionID: z.string(), }) export type Info = z.infer<typeof Info> @@ -29,19 +30,16 @@ export namespace Share { data: z.custom<FileDiff[]>(), }), z.object({ - type: z.literal("session_status"), - data: z.custom<SessionStatus>(), - }), - z.object({ type: z.literal("model"), data: z.custom<Model[]>(), }), ]) export type Data = z.infer<typeof Data> - export const create = fn(Info.pick({ id: true }), async (body) => { + export const create = fn(z.object({ sessionID: z.string() }), async (body) => { const info: Info = { - id: body.id, + id: body.sessionID.slice(-8), + sessionID: body.sessionID, secret: crypto.randomUUID(), } const exists = await get(info.id) @@ -51,8 +49,8 @@ export namespace Share { return info }) - async function get(sessionID: string) { - return Storage.read<Info>(["share", sessionID]) + export async function get(id: string) { + return Storage.read<Info>(["share", id]) } export const remove = fn(Info.pick({ id: true, secret: true }), async (body) => { @@ -66,8 +64,8 @@ export namespace Share { } }) - export async function data(sessionID: string) { - const list = await Storage.list(["share_data", sessionID]) + export async function data(id: string) { + const list = await Storage.list(["share_data", id]) const promises = [] for (const item of list) { promises.push( @@ -85,7 +83,7 @@ export namespace Share { export const sync = fn( z.object({ - share: Info, + share: Info.pick({ id: true, secret: true }), data: Data.array(), }), async (input) => { @@ -112,9 +110,6 @@ export namespace Share { case "session_diff": await Storage.write(["share_data", input.share.id, "session_diff"], item.data) break - case "session_status": - await Storage.write(["share_data", input.share.id, "session_status"], item.data) - break case "model": await Storage.write(["share_data", input.share.id, "model"], item.data) break diff --git a/packages/enterprise/src/core/storage.ts b/packages/enterprise/src/core/storage.ts index fb33ef389..db03e2160 100644 --- a/packages/enterprise/src/core/storage.ts +++ b/packages/enterprise/src/core/storage.ts @@ -19,7 +19,6 @@ export namespace Storage { return { async read(path: string): Promise<string | undefined> { try { - console.log("reading", bucket, path) const command = new GetObjectCommand({ Bucket: bucket, Key: path, diff --git a/packages/enterprise/src/routes/api/[...path].ts b/packages/enterprise/src/routes/api/[...path].ts index bbca171bd..e77c00de9 100644 --- a/packages/enterprise/src/routes/api/[...path].ts +++ b/packages/enterprise/src/routes/api/[...path].ts @@ -37,6 +37,7 @@ app schema: resolver( z .object({ + id: z.string(), url: z.string(), secret: z.string(), }) @@ -50,17 +51,18 @@ app validator("json", z.object({ sessionID: z.string() })), async (c) => { const body = c.req.valid("json") - const share = await Share.create({ id: body.sessionID }) + const share = await Share.create({ sessionID: body.sessionID }) const protocol = c.req.header("x-forwarded-proto") ?? c.req.header("x-forwarded-protocol") ?? "https" const host = c.req.header("x-forwarded-host") ?? c.req.header("host") return c.json({ + id: share.id, secret: share.secret, url: `${protocol}://${host}/share/${share.id}`, }) }, ) .post( - "/share/:sessionID/sync", + "/share/:shareID/sync", describeRoute({ description: "Sync share data", operationId: "share.sync", @@ -75,20 +77,20 @@ app }, }, }), - validator("param", z.object({ sessionID: z.string() })), + validator("param", z.object({ shareID: z.string() })), validator("json", z.object({ secret: z.string(), data: Share.Data.array() })), async (c) => { - const { sessionID } = c.req.valid("param") + const { shareID } = c.req.valid("param") const body = c.req.valid("json") await Share.sync({ - share: { id: sessionID, secret: body.secret }, + share: { id: shareID, secret: body.secret }, data: body.data, }) return c.json({}) }, ) .get( - "/share/:sessionID/data", + "/share/:shareID/data", describeRoute({ description: "Get share data", operationId: "share.data", @@ -103,14 +105,14 @@ app }, }, }), - validator("param", z.object({ sessionID: z.string() })), + validator("param", z.object({ shareID: z.string() })), async (c) => { - const { sessionID } = c.req.valid("param") - return c.json(await Share.data(sessionID)) + const { shareID } = c.req.valid("param") + return c.json(await Share.data(shareID)) }, ) .delete( - "/share/:sessionID", + "/share/:shareID", describeRoute({ description: "Remove a share", operationId: "share.remove", @@ -125,12 +127,12 @@ app }, }, }), - validator("param", z.object({ sessionID: z.string() })), + validator("param", z.object({ shareID: z.string() })), validator("json", z.object({ secret: z.string() })), async (c) => { - const { sessionID } = c.req.valid("param") + const { shareID } = c.req.valid("param") const body = c.req.valid("json") - await Share.remove({ id: sessionID, secret: body.secret }) + await Share.remove({ id: shareID, secret: body.secret }) return c.json({}) }, ) diff --git a/packages/enterprise/src/routes/share/[sessionID].tsx b/packages/enterprise/src/routes/share/[shareID].tsx index 6c29437bc..61f2d23ea 100644 --- a/packages/enterprise/src/routes/share/[sessionID].tsx +++ b/packages/enterprise/src/routes/share/[shareID].tsx @@ -25,9 +25,12 @@ const SessionDataMissingError = NamedError.create( }), ) -const getData = query(async (sessionID) => { - const data = await Share.data(sessionID) +const getData = query(async (shareID) => { + const share = await Share.get(shareID) + if (!share) throw new SessionDataMissingError({ sessionID: shareID }) + const data = await Share.data(shareID) const result: { + sessionID: string session: Session[] session_diff: { [sessionID: string]: FileDiff[] @@ -45,12 +48,13 @@ const getData = query(async (sessionID) => { [sessionID: string]: Model[] } } = { + sessionID: share.sessionID, session: [], session_diff: { - [sessionID]: [], + [share.sessionID]: [], }, session_status: { - [sessionID]: { + [share.sessionID]: { type: "idle", }, }, @@ -64,10 +68,7 @@ const getData = query(async (sessionID) => { result.session.push(item.data) break case "session_diff": - result.session_diff[sessionID] = item.data - break - case "session_status": - result.session_status[sessionID] = item.data + result.session_diff[share.sessionID] = item.data break case "message": result.message[item.data.sessionID] = result.message[item.data.sessionID] ?? [] @@ -78,24 +79,25 @@ const getData = query(async (sessionID) => { result.part[item.data.messageID].push(item.data) break case "model": - result.model[sessionID] = item.data + result.model[share.sessionID] = item.data break } } - const match = Binary.search(result.session, sessionID!, (s) => s.id) - if (!match.found) throw new SessionDataMissingError({ sessionID }) + const match = Binary.search(result.session, share.sessionID, (s) => s.id) + if (!match.found) throw new SessionDataMissingError({ sessionID: share.sessionID }) + console.log(result) return result }, "getShareData") export const route = { - preload: ({ params }) => getData(params.sessionID), + preload: ({ params }) => getData(params.shareID), } satisfies RouteDefinition export default function () { const params = useParams() const data = createAsync(async () => { - if (!params.sessionID) throw new Error("Missing sessionID") - return getData(params.sessionID) + if (!params.shareID) throw new Error("Missing sessionID") + return getData(params.shareID) }) return ( @@ -115,12 +117,12 @@ export default function () { const [store, setStore] = createStore({ messageId: undefined as string | undefined, }) - const match = createMemo(() => Binary.search(data().session, params.sessionID!, (s) => s.id)) - if (!match().found) throw new Error(`Session ${params.sessionID} not found`) + const match = createMemo(() => Binary.search(data().session, data().sessionID, (s) => s.id)) + if (!match().found) throw new Error(`Session ${data().sessionID} not found`) const info = createMemo(() => data().session[match().index]) const messages = createMemo(() => - params.sessionID - ? (data().message[params.sessionID]?.filter((m) => m.role === "user") ?? []).sort( + data().sessionID + ? (data().message[data().sessionID]?.filter((m) => m.role === "user") ?? []).sort( (a, b) => b.time.created - a.time.created, ) : [], @@ -138,8 +140,8 @@ export default function () { } const provider = createMemo(() => activeMessage()?.model?.providerID) const modelID = createMemo(() => activeMessage()?.model?.modelID) - const model = createMemo(() => data().model[params.sessionID!]?.find((m) => m.id === modelID())) - const diffs = createMemo(() => data().session_diff[params.sessionID!] ?? []) + const model = createMemo(() => data().model[data().sessionID]?.find((m) => m.id === modelID())) + const diffs = createMemo(() => data().session_diff[data().sessionID] ?? []) const title = () => ( <div class="flex flex-col gap-4 shrink-0"> @@ -167,7 +169,7 @@ export default function () { <For each={messages()}> {(message) => ( <SessionTurn - sessionID={params.sessionID!} + sessionID={data().sessionID} messageID={message.id} classes={{ root: "min-w-0 w-full relative", @@ -254,7 +256,7 @@ export default function () { </> </Show> <SessionTurn - sessionID={params.sessionID!} + sessionID={data().sessionID} messageID={store.messageId ?? firstUserMessage()!.id!} classes={{ root: "grow", content: "flex flex-col justify-between", container: "pb-20" }} > |
