share.ts 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { Bus } from "../bus"
  2. import { Installation } from "../installation"
  3. import { Session } from "../session"
  4. import { MessageV2 } from "../session/message-v2"
  5. import { Log } from "../util/log"
  6. export namespace Share {
  7. const log = Log.create({ service: "share" })
  8. let queue: Promise<void> = Promise.resolve()
  9. const pending = new Map<string, any>()
  10. export async function sync(key: string, content: any) {
  11. const [root, ...splits] = key.split("/")
  12. if (root !== "session") return
  13. const [sub, sessionID] = splits
  14. if (sub === "share") return
  15. const share = await Session.getShare(sessionID).catch(() => {})
  16. if (!share) return
  17. const { secret } = share
  18. pending.set(key, content)
  19. queue = queue
  20. .then(async () => {
  21. const content = pending.get(key)
  22. if (content === undefined) return
  23. pending.delete(key)
  24. return fetch(`${URL}/share_sync`, {
  25. method: "POST",
  26. body: JSON.stringify({
  27. sessionID: sessionID,
  28. secret,
  29. key: key,
  30. content,
  31. }),
  32. })
  33. })
  34. .then((x) => {
  35. if (x) {
  36. log.info("synced", {
  37. key: key,
  38. status: x.status,
  39. })
  40. }
  41. })
  42. }
  43. export function init() {
  44. Bus.subscribe(Session.Event.Updated, async (evt) => {
  45. await sync("session/info/" + evt.properties.info.id, evt.properties.info)
  46. })
  47. Bus.subscribe(MessageV2.Event.Updated, async (evt) => {
  48. await sync("session/message/" + evt.properties.info.sessionID + "/" + evt.properties.info.id, evt.properties.info)
  49. })
  50. Bus.subscribe(MessageV2.Event.PartUpdated, async (evt) => {
  51. await sync(
  52. "session/part/" +
  53. evt.properties.part.sessionID +
  54. "/" +
  55. evt.properties.part.messageID +
  56. "/" +
  57. evt.properties.part.id,
  58. evt.properties.part,
  59. )
  60. })
  61. }
  62. export const URL =
  63. process.env["OPENCODE_API"] ??
  64. (Installation.isPreview() || Installation.isLocal() ? "https://api.dev.opencode.ai" : "https://api.opencode.ai")
  65. export async function create(sessionID: string) {
  66. return fetch(`${URL}/share_create`, {
  67. method: "POST",
  68. body: JSON.stringify({ sessionID: sessionID }),
  69. })
  70. .then((x) => x.json())
  71. .then((x) => x as { url: string; secret: string })
  72. }
  73. export async function remove(sessionID: string, secret: string) {
  74. return fetch(`${URL}/share_delete`, {
  75. method: "POST",
  76. body: JSON.stringify({ sessionID, secret }),
  77. }).then((x) => x.json())
  78. }
  79. }