diff --git a/apps/app/src/app/lib/den.ts b/apps/app/src/app/lib/den.ts index e6e429270..a5772d6a3 100644 --- a/apps/app/src/app/lib/den.ts +++ b/apps/app/src/app/lib/den.ts @@ -29,6 +29,7 @@ const STORAGE_AUTH_TOKEN = "openwork.den.authToken"; const STORAGE_ACTIVE_ORG_ID = "openwork.den.activeOrgId"; const STORAGE_ACTIVE_ORG_SLUG = "openwork.den.activeOrgSlug"; const STORAGE_ACTIVE_ORG_NAME = "openwork.den.activeOrgName"; +const ORG_PROXY_HEADER = "x-openwork-legacy-org-id"; const DEFAULT_DEN_TIMEOUT_MS = 12_000; export const DEFAULT_DEN_AUTH_NAME = "OpenWork User"; @@ -1135,6 +1136,14 @@ const resolveFetch = () => (isDesktopRuntime() ? desktopFetch : globalThis.fetch type FetchLike = (input: RequestInfo | URL, init?: RequestInit) => Promise; +type DenRequestOptions = { + method?: string; + token?: string | null; + body?: unknown; + timeoutMs?: number; + organizationId?: string | null; +}; + async function fetchWithTimeout(fetchImpl: FetchLike, url: string, init: RequestInit, timeoutMs: number) { if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) { return fetchImpl(url, init); @@ -1166,7 +1175,7 @@ async function fetchWithTimeout(fetchImpl: FetchLike, url: string, init: Request async function requestJsonRaw( input: string | DenBaseUrls, path: string, - options: { method?: string; token?: string | null; body?: unknown; timeoutMs?: number } = {}, + options: DenRequestOptions = {}, ): Promise> { const baseUrls = typeof input === "string" ? resolveDenBaseUrls(input) : input; const url = `${resolveRequestBaseUrl(baseUrls, path)}${path}`; @@ -1175,6 +1184,10 @@ async function requestJsonRaw( if (token) { headers.Authorization = `Bearer ${token}`; } + const organizationId = options.organizationId?.trim() ?? ""; + if (organizationId) { + headers[ORG_PROXY_HEADER] = organizationId; + } if (options.body !== undefined) { headers["Content-Type"] = "application/json"; } @@ -1204,7 +1217,7 @@ async function requestJsonRaw( async function requestJson( input: string | DenBaseUrls, path: string, - options: { method?: string; token?: string | null; body?: unknown; timeoutMs?: number } = {}, + options: DenRequestOptions = {}, ): Promise { const raw = await requestJsonRaw(input, path, options); if (!raw.ok) { @@ -1346,6 +1359,7 @@ export function createDenClient(options: { baseUrl: string; apiBaseUrl?: string const payload = await requestJson(baseUrls, `/v1/workers?${params.toString()}`, { method: "GET", token, + organizationId: orgId, }); return getWorkers(payload); }, @@ -1354,6 +1368,7 @@ export function createDenClient(options: { baseUrl: string; apiBaseUrl?: string const payload = await requestJson(baseUrls, `/v1/workers/${encodeURIComponent(workerId)}/tokens`, { method: "POST", token, + organizationId: orgId, body: {}, }); const tokens = getWorkerTokens(payload); @@ -1367,6 +1382,7 @@ export function createDenClient(options: { baseUrl: string; apiBaseUrl?: string const payload = await requestJson(baseUrls, "/v1/skills", { method: "GET", token, + organizationId: orgId, }); return getDenOrgSkillsFromPayload(payload); }, @@ -1375,6 +1391,7 @@ export function createDenClient(options: { baseUrl: string; apiBaseUrl?: string const payload = await requestJson(baseUrls, "/v1/skill-hubs", { method: "GET", token, + organizationId: orgId, }); return getDenOrgSkillHubsFromPayload(payload); }, @@ -1383,6 +1400,7 @@ export function createDenClient(options: { baseUrl: string; apiBaseUrl?: string const payload = await requestJson(baseUrls, "/v1/skill-hubs", { method: "GET", token, + organizationId: orgId, }); return getOrgSkillHubSummaries(payload); }, @@ -1398,6 +1416,7 @@ export function createDenClient(options: { baseUrl: string; apiBaseUrl?: string const payload = await requestJson(baseUrls, "/v1/skills", { method: "POST", token, + organizationId: orgId, body, }); const id = getCreatedOrgSkillId(payload); @@ -1414,6 +1433,7 @@ export function createDenClient(options: { baseUrl: string; apiBaseUrl?: string { method: "POST", token, + organizationId: orgId, body: { skillId }, }, ); @@ -1423,6 +1443,7 @@ export function createDenClient(options: { baseUrl: string; apiBaseUrl?: string const payload = await requestJson(baseUrls, "/v1/llm-providers", { method: "GET", token, + organizationId: orgId, }); return getDenOrgLlmProviders(payload); }, @@ -1434,6 +1455,7 @@ export function createDenClient(options: { baseUrl: string; apiBaseUrl?: string { method: "GET", token, + organizationId: orgId, }, ); const provider = getDenOrgLlmProviderConnection(payload); @@ -1447,7 +1469,7 @@ export function createDenClient(options: { baseUrl: string; apiBaseUrl?: string const payload = await requestJson( baseUrls, `/v1/marketplaces?status=active&limit=100`, - { method: "GET", token }, + { method: "GET", token, organizationId: orgId }, ); return getOrgMarketplaces(payload); }, @@ -1456,7 +1478,7 @@ export function createDenClient(options: { baseUrl: string; apiBaseUrl?: string const payload = await requestJson( baseUrls, `/v1/marketplaces/${encodeURIComponent(marketplaceId)}/resolved`, - { method: "GET", token }, + { method: "GET", token, organizationId: orgId }, ); const resolved = getOrgMarketplaceResolved(payload); if (!resolved) { @@ -1469,7 +1491,7 @@ export function createDenClient(options: { baseUrl: string; apiBaseUrl?: string const payload = await requestJson( baseUrls, `/v1/plugins/${encodeURIComponent(plugin.id)}/resolved`, - { method: "GET", token }, + { method: "GET", token, organizationId: orgId }, ); return getOrgPluginResolved(plugin, payload); }, diff --git a/apps/app/src/react-app/domains/settings/panels/den-settings-panel.tsx b/apps/app/src/react-app/domains/settings/panels/den-settings-panel.tsx index 57ce60766..e3a0ec7cd 100644 --- a/apps/app/src/react-app/domains/settings/panels/den-settings-panel.tsx +++ b/apps/app/src/react-app/domains/settings/panels/den-settings-panel.tsx @@ -835,6 +835,7 @@ export function DenSettingsPanel(props: DenSettingsPanelProps) { if (!quiet) setPluginActionError(null); try { + syncCurrentDenSettings(); await props.extensions.refreshCloudOrgMarketplaces({ force: true }); if (!quiet) { const count = props.extensions.cloudOrgMarketplaces().length; @@ -853,7 +854,7 @@ export function DenSettingsPanel(props: DenSettingsPanelProps) { setMarketplacesBusy(false); } }, - [activeOrg, activeOrgId, authToken, props.extensions, showToast], + [activeOrg, activeOrgId, authToken, props.extensions, showToast, syncCurrentDenSettings], ); React.useEffect(() => { diff --git a/ee/apps/den-api/src/app.ts b/ee/apps/den-api/src/app.ts index 39d118e87..606217596 100644 --- a/ee/apps/den-api/src/app.ts +++ b/ee/apps/den-api/src/app.ts @@ -58,7 +58,7 @@ if (env.corsOrigins.length > 0) { cors({ origin: env.corsOrigins, credentials: true, - allowHeaders: ["Content-Type", "Authorization", "X-Api-Key", "X-Request-Id"], + allowHeaders: ["Content-Type", "Authorization", "X-Api-Key", "X-Request-Id", "X-OpenWork-Legacy-Org-Id"], allowMethods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"], exposeHeaders: ["Content-Length", "X-Request-Id"], maxAge: 600,