remote-codex 0.11.25 → 0.11.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -403,6 +403,9 @@ var RelayStore = class _RelayStore {
403
403
  sharedByMe: sharedByMe.map((share) => this.publicShare(share))
404
404
  };
405
405
  }
406
+ sharedThreadsForDevice(userId, deviceId) {
407
+ return this.getSharesByTarget(userId).filter((share) => share.deviceId === deviceId).map((share) => this.publicShare(share));
408
+ }
406
409
  adminSummary(connectedDevices, options = {}) {
407
410
  const conversationWindowDays = normalizeConversationWindowDays(options.conversationWindowDays);
408
411
  const users = this.getUsers();
@@ -1847,16 +1850,40 @@ function applyWebViewCorsHeaders(reply, origin) {
1847
1850
  async function forwardRelayHttp(input) {
1848
1851
  const threadId = threadIdFromPath(input.targetPath);
1849
1852
  const workspaceId = workspaceIdFromPath(input.targetPath);
1853
+ const targetUrl = new URL(input.targetPath, "http://relay.local");
1854
+ const sharedThreadListRequest = input.request.method.toUpperCase() === "GET" && targetUrl.pathname === "/api/threads";
1855
+ const sharedRuntimeMetadataRequest = isAllowedSharedRuntimeMetadataRequest(
1856
+ input.request.method,
1857
+ targetUrl.pathname
1858
+ );
1850
1859
  const access = input.store.effectiveAccess(input.user.id, input.deviceId, {
1851
1860
  threadId,
1852
1861
  workspaceId
1853
1862
  });
1863
+ let allowSharedRuntimeMetadata = false;
1854
1864
  if (!access) {
1855
- input.reply.status(403).send({
1856
- code: "forbidden",
1857
- message: "Device access is not allowed."
1858
- });
1859
- return;
1865
+ const shares = sharedThreadListRequest || sharedRuntimeMetadataRequest ? input.store.sharedThreadsForDevice(input.user.id, input.deviceId) : [];
1866
+ if (sharedThreadListRequest) {
1867
+ if (shares.length > 0) {
1868
+ await forwardSharedThreadList({
1869
+ reply: input.reply,
1870
+ state: input.state,
1871
+ store: input.store,
1872
+ user: input.user,
1873
+ deviceId: input.deviceId,
1874
+ shares
1875
+ });
1876
+ return;
1877
+ }
1878
+ }
1879
+ allowSharedRuntimeMetadata = sharedRuntimeMetadataRequest && shares.length > 0;
1880
+ if (!allowSharedRuntimeMetadata) {
1881
+ input.reply.status(403).send({
1882
+ code: "forbidden",
1883
+ message: "Device access is not allowed."
1884
+ });
1885
+ return;
1886
+ }
1860
1887
  }
1861
1888
  if (!isAllowedRelayTarget(input.targetPath)) {
1862
1889
  input.reply.status(403).send({
@@ -1865,14 +1892,14 @@ async function forwardRelayHttp(input) {
1865
1892
  });
1866
1893
  return;
1867
1894
  }
1868
- if (!isAllowedForRelayAccess(access, input.request.method, input.targetPath)) {
1895
+ if (access && !isAllowedForRelayAccess(access, input.request.method, input.targetPath)) {
1869
1896
  input.reply.status(403).send({
1870
1897
  code: "forbidden",
1871
1898
  message: "This shared session does not allow that operation."
1872
1899
  });
1873
1900
  return;
1874
1901
  }
1875
- if (access.kind === "shared") {
1902
+ if (access?.kind === "shared") {
1876
1903
  input.store.recordShareAccess(access.share, input.user);
1877
1904
  }
1878
1905
  const conversationEvent = conversationEventFromRequest(
@@ -1926,6 +1953,30 @@ async function forwardRelayHttp(input) {
1926
1953
  });
1927
1954
  }
1928
1955
  }
1956
+ async function forwardSharedThreadList(input) {
1957
+ const supervisor = input.state.supervisors.get(input.deviceId);
1958
+ if (!supervisor || supervisor.socket.readyState !== WEBSOCKET_OPEN) {
1959
+ input.reply.status(503).send({
1960
+ code: "service_unavailable",
1961
+ message: "No supervisor is connected for this device."
1962
+ });
1963
+ return;
1964
+ }
1965
+ const threads = await Promise.all(
1966
+ input.shares.map(async (share) => {
1967
+ input.store.recordShareAccess(share, input.user);
1968
+ const payload = await forwardSupervisorJson(
1969
+ supervisor,
1970
+ input.deviceId,
1971
+ `/api/threads/${encodeURIComponent(share.threadId)}?limit=1`,
1972
+ { timeoutMs: RELAY_REQUEST_TIMEOUT_MS }
1973
+ );
1974
+ const thread = isObject(payload) && isObject(payload.thread) ? payload.thread : payload;
1975
+ return isObject(thread) ? thread : null;
1976
+ })
1977
+ );
1978
+ input.reply.send(threads.filter((thread) => Boolean(thread)));
1979
+ }
1929
1980
  function relayResponseBody(response) {
1930
1981
  if (response.bodyEncoding === "base64") {
1931
1982
  return Buffer.from(response.body, "base64");
@@ -2244,7 +2295,7 @@ async function fetchRelayWorkspaceLabel(supervisor, deviceId, workspaceId) {
2244
2295
  const payload = await forwardSupervisorJson(supervisor, deviceId, `/api/workspaces/${encodeURIComponent(workspaceId)}`);
2245
2296
  return stringField(payload, "label");
2246
2297
  }
2247
- async function forwardSupervisorJson(supervisor, deviceId, targetPath) {
2298
+ async function forwardSupervisorJson(supervisor, deviceId, targetPath, options = {}) {
2248
2299
  try {
2249
2300
  const response = await supervisor.requestBroker.forward(
2250
2301
  supervisor.socket,
@@ -2260,7 +2311,7 @@ async function forwardSupervisorJson(supervisor, deviceId, targetPath) {
2260
2311
  body: null
2261
2312
  }
2262
2313
  },
2263
- { timeoutMs: RELAY_PORTAL_METADATA_TIMEOUT_MS }
2314
+ { timeoutMs: options.timeoutMs ?? RELAY_PORTAL_METADATA_TIMEOUT_MS }
2264
2315
  );
2265
2316
  if (response.statusCode < 200 || response.statusCode >= 300) {
2266
2317
  return null;
@@ -2308,6 +2359,15 @@ function isAllowedRelayTarget(pathValue) {
2308
2359
  const pathname = new URL(pathValue, "http://relay.local").pathname;
2309
2360
  return pathname === "/healthz" || pathname.startsWith("/api/");
2310
2361
  }
2362
+ function isAllowedSharedRuntimeMetadataRequest(method, pathname) {
2363
+ if (method.toUpperCase() !== "GET") {
2364
+ return false;
2365
+ }
2366
+ if (pathname === "/api/agent-runtimes") {
2367
+ return true;
2368
+ }
2369
+ return /^\/api\/agent-runtimes\/[^/]+\/(?:status|models)$/.test(pathname);
2370
+ }
2311
2371
  function threadIdFromPath(pathValue) {
2312
2372
  const pathname = new URL(pathValue, "http://relay.local").pathname;
2313
2373
  const match = /^\/api\/threads\/([^/?#]+)/.exec(pathname);