Compare commits

..

1 Commits

Author SHA1 Message Date
dadachann bf5170ea52 fix(web): restore plugin page SDK loading 2026-08-14 10:21:18 +00:00
2 changed files with 82 additions and 6 deletions
+24 -2
View File
@@ -710,11 +710,32 @@ export class BackendClient extends BaseHttpClient {
); );
} }
private async getAuthenticatedObjectURL(path: string): Promise<string> { private async getAuthenticatedObjectURL(
path: string,
rewritePluginPageSdk = false,
): Promise<string> {
const response = await this.instance.get<Blob>(path, { const response = await this.instance.get<Blob>(path, {
responseType: 'blob', responseType: 'blob',
}); });
return URL.createObjectURL(response.data); let blob = response.data;
if (rewritePluginPageSdk && blob.type.startsWith('text/html')) {
const apiBase =
this.instance.defaults.baseURL === '/'
? window.location.origin
: this.instance.defaults.baseURL?.replace(/\/$/, '');
const pageSdkUrl = `${apiBase}/api/v1/plugins/_sdk/page-sdk.js`;
const html = await blob.text();
blob = new Blob(
[
html.replace(
/(<script\b[^>]*\bsrc\s*=\s*)(["'])\/api\/v1\/plugins\/_sdk\/page-sdk\.js\2/gi,
`$1$2${pageSdkUrl}$2`,
),
],
{ type: blob.type },
);
}
return URL.createObjectURL(blob);
} }
public getAuthenticatedPluginAssetURL( public getAuthenticatedPluginAssetURL(
@@ -724,6 +745,7 @@ export class BackendClient extends BaseHttpClient {
): Promise<string> { ): Promise<string> {
return this.getAuthenticatedObjectURL( return this.getAuthenticatedObjectURL(
`/api/v1/plugins/${author}/${name}/authenticated-assets/${filepath}`, `/api/v1/plugins/${author}/${name}/authenticated-assets/${filepath}`,
true,
); );
} }
+58 -4
View File
@@ -69,7 +69,55 @@ test('loads a Cloud plugin page through the authenticated asset route', async ({
await route.fulfill({ await route.fulfill({
status: 200, status: 200,
contentType: 'text/html', contentType: 'text/html',
body: '<!doctype html><html><body><h1>LangRAG Observability</h1></body></html>', body: `<!doctype html>
<html>
<body>
<h1>LangRAG Observability</h1>
<button id="save">Save</button>
<script src="/api/v1/plugins/_sdk/page-sdk.js"></script>
<script>
document.querySelector('#save').addEventListener('click', async () => {
await window.langbot.api('/settings', { enabled: true }, 'POST');
document.body.dataset.saved = 'true';
});
</script>
</body>
</html>`,
});
},
);
let pageSdkRequests = 0;
await page.route('**/api/v1/plugins/_sdk/page-sdk.js', async (route) => {
pageSdkRequests += 1;
await route.fulfill({
status: 200,
contentType: 'application/javascript',
body: `window.langbot = {
api(endpoint, body, method) {
return new Promise((resolve) => {
const requestId = 'request-' + Date.now();
const handler = (event) => {
if (event.data?.type === 'langbot:api:response' && event.data.requestId === requestId) {
window.removeEventListener('message', handler);
resolve(event.data.data);
}
};
window.addEventListener('message', handler);
window.parent.postMessage({ type: 'langbot:api', requestId, endpoint, body, method }, '*');
});
},
};`,
});
});
let pageApiRequests = 0;
await page.route(
'**/api/v1/plugins/langbot-team/LangRAG/page-api',
async (route) => {
pageApiRequests += 1;
await route.fulfill({
status: 200,
contentType: 'application/json',
body: wrapped({ saved: true }),
}); });
}, },
); );
@@ -78,11 +126,17 @@ test('loads a Cloud plugin page through the authenticated asset route', async ({
'/home/plugin-pages?id=langbot-team%2FLangRAG%2Fobservability', '/home/plugin-pages?id=langbot-team%2FLangRAG%2Fobservability',
); );
const pluginFrame = page.frameLocator('iframe');
await expect( await expect(
page pluginFrame.getByRole('heading', { name: 'LangRAG Observability' }),
.frameLocator('iframe')
.getByRole('heading', { name: 'LangRAG Observability' }),
).toBeVisible(); ).toBeVisible();
await pluginFrame.getByRole('button', { name: 'Save' }).click();
await expect(pluginFrame.locator('body')).toHaveAttribute(
'data-saved',
'true',
);
expect(authenticatedAssetRequests).toBeGreaterThan(0); expect(authenticatedAssetRequests).toBeGreaterThan(0);
expect(pageSdkRequests).toBe(1);
expect(pageApiRequests).toBe(1);
await expect(page.getByText('Loading...')).toHaveCount(0); await expect(page.getByText('Loading...')).toHaveCount(0);
}); });