@standardagents/builder 0.38.0 → 0.38.1

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.
Files changed (54) hide show
  1. package/dist/built-in-routes.js +1165 -366
  2. package/dist/built-in-routes.js.map +1 -1
  3. package/dist/client/{ApiKeysView-L85eJb6G.js → ApiKeysView-AH5i-H6j.js} +1 -1
  4. package/dist/client/CenteredContentView-DaBp0K-A.js +1 -0
  5. package/dist/client/{CompositionView-BGp0EJCk.js → CompositionView-yY1Q4M23.js} +1 -1
  6. package/dist/client/{ConfirmDialog.vue_vue_type_script_setup_true_lang-DgwqZrLV.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-Bwo5CJzF.js} +1 -1
  7. package/dist/client/{CopyButton.vue_vue_type_script_setup_true_lang-B8cGgU2J.js → CopyButton.vue_vue_type_script_setup_true_lang-D0WYwWyA.js} +1 -1
  8. package/dist/client/{DataTable.vue_vue_type_script_setup_true_lang-CRBXym9D.js → DataTable.vue_vue_type_script_setup_true_lang-1wwPn2aY.js} +1 -1
  9. package/dist/client/{JsonViewer-DkHnIfq3.js → JsonViewer-Bi8Zdmir.js} +1 -1
  10. package/dist/client/LoginView-BIKahEU6.js +1 -0
  11. package/dist/client/{MarketplaceView-DEnujUBs.js → MarketplaceView-DPDPVH68.js} +1 -1
  12. package/dist/client/{Modal.vue_vue_type_script_setup_true_lang-keKEwm3K.js → Modal.vue_vue_type_script_setup_true_lang-D1_rfOsy.js} +1 -1
  13. package/dist/client/{ModelModal.vue_vue_type_script_setup_true_lang-t1n0bbJe.js → ModelModal.vue_vue_type_script_setup_true_lang-DSLeOdxr.js} +1 -1
  14. package/dist/client/{ModelsView-BkCLr8sp.js → ModelsView-Q2WXu1Gw.js} +1 -1
  15. package/dist/client/{PromptEditView-BjCfsJQE.js → PromptEditView-BzA-3n1w.js} +1 -1
  16. package/dist/client/{PromptModal-nxu_LIv6.js → PromptModal-CJWh_cru.js} +1 -1
  17. package/dist/client/{PromptsView-1yXGCmEZ.js → PromptsView-BezNl-Et.js} +1 -1
  18. package/dist/client/{ProvidersView-DxF6gafk.js → ProvidersView-BuzSKxuT.js} +1 -1
  19. package/dist/client/ThreadInspectorPane.vue_vue_type_script_setup_true_lang-DOxNp_3C.js +22 -0
  20. package/dist/client/{ThreadsView-CBup_w8u.js → ThreadsView-DPCpZA4J.js} +1 -1
  21. package/dist/client/{ToolsView-B30TfXU9.js → ToolsView-DMjFMAhH.js} +1 -1
  22. package/dist/client/{UiCodeBlock.vue_vue_type_script_setup_true_lang-BdyzSxZZ.js → UiCodeBlock.vue_vue_type_script_setup_true_lang-7FgZmkfs.js} +1 -1
  23. package/dist/client/{UsersView-kE7Xr4f3.js → UsersView-B7jXLNQs.js} +1 -1
  24. package/dist/client/{VariablesView-yYuynG0M.js → VariablesView-CF7x0G8g.js} +1 -1
  25. package/dist/client/assets/{ThreadInspectorPane-BRGO_P0_.css → ThreadInspectorPane-CZMdV0Tb.css} +1 -1
  26. package/dist/client/assets/{index-B-69GGhJ.css → index-DAABRRAA.css} +1 -1
  27. package/dist/client/{check-YKi1o6p6.js → check-CD2lvcVi.js} +1 -1
  28. package/dist/client/{chevron-right-T0zzq_GX.js → chevron-right-bWZrmJ5a.js} +1 -1
  29. package/dist/client/{copy-C_gUGAj1.js → copy-B7nifl6a.js} +1 -1
  30. package/dist/client/{formkit-CE26dtFp.js → formkit-DJxUzqRQ.js} +1 -1
  31. package/dist/client/index-eGECJFYe.js +6 -0
  32. package/dist/client/index.html +6 -6
  33. package/dist/client/{package-B70IFSDB.js → package-Dyv7fTIQ.js} +1 -1
  34. package/dist/client/{plus-BN9IHYdt.js → plus-XkSslfF4.js} +1 -1
  35. package/dist/client/{syntax-D-ZcovVx.js → syntax-D68HCEYm.js} +1 -1
  36. package/dist/client/{timeAgo-G1ovbWPH.js → timeAgo-DRBdu9ed.js} +1 -1
  37. package/dist/client/{useActionFeedback-7pfPjKMi.js → useActionFeedback-FN4t6ezB.js} +1 -1
  38. package/dist/client/{vendor-TPZjEwCU.js → vendor-c_uwtQ-S.js} +13 -13
  39. package/dist/client/{vue-CZ-ORfS3.js → vue-BuvSxRmI.js} +1 -1
  40. package/dist/{index-BBu-Osn5.d.ts → index-CF-lgN47.d.ts} +74 -11
  41. package/dist/index.d.ts +2 -2
  42. package/dist/index.js +1060 -303
  43. package/dist/index.js.map +1 -1
  44. package/dist/plugin.js +102 -68
  45. package/dist/plugin.js.map +1 -1
  46. package/dist/runtime.d.ts +68 -11
  47. package/dist/runtime.js +950 -225
  48. package/dist/runtime.js.map +1 -1
  49. package/dist/test.d.ts +1 -1
  50. package/package.json +7 -6
  51. package/dist/client/CenteredContentView-D9jkWoLc.js +0 -1
  52. package/dist/client/LoginView-BXD9Odc-.js +0 -1
  53. package/dist/client/ThreadInspectorPane.vue_vue_type_script_setup_true_lang-CjwWJ3uw.js +0 -22
  54. package/dist/client/index-AUGwDdSH.js +0 -6
package/dist/plugin.js CHANGED
@@ -689,6 +689,27 @@ declare module 'virtual:@standardagents/builder' {
689
689
  validateSession(tokenHash: string): Promise<{ user_id: string; expires_at: number } | null>;
690
690
  cleanupSessions(): Promise<number>;
691
691
  deleteSession(tokenHash: string): Promise<void>;
692
+ createSuperAdminSession(params: {
693
+ token_hash: string;
694
+ expires_at: number;
695
+ }): Promise<void>;
696
+ validateSuperAdminSession(tokenHash: string): Promise<boolean>;
697
+ deleteSuperAdminSession(tokenHash: string): Promise<void>;
698
+ createWebSocketTicket(params: {
699
+ ticket_hash: string;
700
+ pathname: string;
701
+ auth_json: string;
702
+ expires_at: number;
703
+ }): Promise<void>;
704
+ consumeWebSocketTicket(params: {
705
+ ticket_hash: string;
706
+ pathname: string;
707
+ }): Promise<string | null>;
708
+ consumeAuthRateLimit(params: {
709
+ key: string;
710
+ limit: number;
711
+ window_seconds: number;
712
+ }): Promise<{ allowed: boolean; retry_after: number; remaining: number }>;
692
713
 
693
714
  // API key methods
694
715
  createApiKey(params: {
@@ -1289,6 +1310,7 @@ function resolveLocalBootstrapCookie(projectRoot, routePath, cookieHeader) {
1289
1310
  if (hasSessionCookie(cookieHeader)) return null;
1290
1311
  return findLocalBootstrapSession(projectRoot)?.session.session_cookie ?? null;
1291
1312
  }
1313
+ var SESSION_COOKIE_NAME = "agtuser_session";
1292
1314
 
1293
1315
  // src/sdk/generators/generateModelFile.ts
1294
1316
  function generateModelFile(data, options) {
@@ -1355,7 +1377,7 @@ function generateModelFile(data, options) {
1355
1377
  return lines.join("\n");
1356
1378
  }
1357
1379
  function escapeString(str) {
1358
- return str.replace(/'/g, "\\'").replace(/\\/g, "\\\\");
1380
+ return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1359
1381
  }
1360
1382
 
1361
1383
  // src/sdk/generators/jsonSchemaToZod.ts
@@ -1886,7 +1908,7 @@ function formatSideConfig(config) {
1886
1908
  return parts.join("\n");
1887
1909
  }
1888
1910
  function escapeString3(str) {
1889
- return str.replace(/'/g, "\\'").replace(/\\/g, "\\\\");
1911
+ return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
1890
1912
  }
1891
1913
  function formatSessionBinding(binding) {
1892
1914
  if (typeof binding === "string") {
@@ -6695,7 +6717,7 @@ function isProviderIconRoute(routePath) {
6695
6717
  return /^\/api\/providers\/[^/]+\/icon$/.test(routePath);
6696
6718
  }
6697
6719
  function isHostedInstance(env) {
6698
- const value = env?.STANDARD_AGENTS_HOSTED;
6720
+ const value = env && typeof env === "object" ? Reflect.get(env, "STANDARD_AGENTS_HOSTED") : void 0;
6699
6721
  if (typeof value === "string") {
6700
6722
  const normalized = value.trim().toLowerCase();
6701
6723
  return normalized !== "" && normalized !== "0" && normalized !== "false";
@@ -6713,6 +6735,7 @@ function isTrustedLocalDevelopmentRequest(request, env) {
6713
6735
  return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname.endsWith(".localhost") || hostname.endsWith(".orb.local");
6714
6736
  }
6715
6737
  function isAdminOnlyApiRoute(routePath, method = "GET") {
6738
+ if (routePath === "/api/hooks") return true;
6716
6739
  if (routePath === "/api/skills" || routePath.startsWith("/api/skills/")) return true;
6717
6740
  if (routePath === "/api/pack" || routePath.startsWith("/api/pack/")) return true;
6718
6741
  if (routePath === "/api/unpack" || routePath.startsWith("/api/unpack/")) return true;
@@ -6731,6 +6754,9 @@ function isAdminOnlyApiRoute(routePath, method = "GET") {
6731
6754
  }
6732
6755
 
6733
6756
  // src/plugin/dev-middleware.ts
6757
+ function isEncryptedSocket(socket) {
6758
+ return "encrypted" in socket && socket.encrypted === true;
6759
+ }
6734
6760
  function readRawRequestBody(req) {
6735
6761
  return new Promise((resolve3, reject) => {
6736
6762
  const chunks = [];
@@ -6755,6 +6781,36 @@ function resolveContainedFile(baseDir, requestPath) {
6755
6781
  return null;
6756
6782
  }
6757
6783
  }
6784
+ function firstHeader(value) {
6785
+ return Array.isArray(value) ? value[0] : value;
6786
+ }
6787
+ function isSameOriginDevRequest(req) {
6788
+ const fetchSite = firstHeader(req.headers["sec-fetch-site"])?.trim().toLowerCase();
6789
+ if (fetchSite && fetchSite !== "same-origin" && fetchSite !== "none") {
6790
+ return false;
6791
+ }
6792
+ const origin = firstHeader(req.headers.origin)?.trim();
6793
+ if (!origin) return true;
6794
+ if (origin === "null") return false;
6795
+ try {
6796
+ const forwardedProtocol = firstHeader(req.headers["x-forwarded-proto"])?.split(",")[0]?.trim().toLowerCase();
6797
+ const protocol = forwardedProtocol === "https" || forwardedProtocol === "http" ? forwardedProtocol : isEncryptedSocket(req.socket) ? "https" : "http";
6798
+ const requestOrigin = new URL(`${protocol}://${String(req.headers.host || "").trim()}`).origin;
6799
+ return new URL(origin).origin === requestOrigin;
6800
+ } catch {
6801
+ return false;
6802
+ }
6803
+ }
6804
+ function hasDevAuthoringCredential(req) {
6805
+ const cookie = firstHeader(req.headers.cookie) || "";
6806
+ const hasSession = cookie.split(";").some((part) => {
6807
+ const separator = part.indexOf("=");
6808
+ return separator !== -1 && part.slice(0, separator).trim() === SESSION_COOKIE_NAME && part.slice(separator + 1).trim() !== "";
6809
+ });
6810
+ if (hasSession) return true;
6811
+ const authorization = firstHeader(req.headers.authorization)?.trim() || "";
6812
+ return /^Bearer\s+\S+$/.test(authorization);
6813
+ }
6758
6814
  function injectUiConfigIntoHtml(htmlContent) {
6759
6815
  const configScript = `<script>window.__AGENTBUILDER_CONFIG__ = { devMode: true };</script>`;
6760
6816
  return htmlContent.replace(/\/agents\//g, "/").replace("</head>", `${configScript}</head>`);
@@ -6809,11 +6865,21 @@ function createDevMiddleware(server, context) {
6809
6865
  );
6810
6866
  } catch {
6811
6867
  }
6812
- if (isAdminOnlyApiRoute(routePath, method) && !trustedLocalHost) {
6813
- res.statusCode = 403;
6814
- res.setHeader("Content-Type", "application/json");
6815
- res.end(JSON.stringify({ error: "Authoring APIs are available only from local development hosts" }));
6816
- return;
6868
+ if (isAdminOnlyApiRoute(routePath, method)) {
6869
+ if (!trustedLocalHost || !isSameOriginDevRequest(req)) {
6870
+ res.statusCode = 403;
6871
+ res.setHeader("Content-Type", "application/json");
6872
+ res.setHeader("Cache-Control", "no-store");
6873
+ res.end(JSON.stringify({ error: "Authoring APIs require a same-origin local request" }));
6874
+ return;
6875
+ }
6876
+ if (!hasDevAuthoringCredential(req)) {
6877
+ res.statusCode = 401;
6878
+ res.setHeader("Content-Type", "application/json");
6879
+ res.setHeader("Cache-Control", "no-store");
6880
+ res.end(JSON.stringify({ error: "Authoring APIs require an authenticated local session" }));
6881
+ return;
6882
+ }
6817
6883
  }
6818
6884
  if (await handleConfigApiRequest({
6819
6885
  req,
@@ -7468,8 +7534,13 @@ import {
7468
7534
  canAccessThread,
7469
7535
  endpointCallerFromAuth,
7470
7536
  isHostedInstance,
7537
+ isTrustedLocalDevelopmentRequest,
7538
+ isSameOriginBrowserRequest,
7471
7539
  isPublicApiRoute,
7472
7540
  isAdminOnlyApiRoute,
7541
+ applyRuntimeCors,
7542
+ runtimeCorsHeaders,
7543
+ runtimePreflightResponse,
7473
7544
  } from "@standardagents/builder/runtime";
7474
7545
  import { isThreadEndpoint, getEndpointAccess } from "@standardagents/spec";
7475
7546
 
@@ -7526,71 +7597,34 @@ function isHtmlNavigationRequest(request) {
7526
7597
  return (accept === '' || accept === '*/*') && isUiNavigationPath(pathname);
7527
7598
  }
7528
7599
 
7529
- // CORS headers for API responses
7530
- const CORS_HEADERS = {
7531
- "Access-Control-Allow-Origin": "*",
7532
- "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
7533
- "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With",
7534
- "Access-Control-Max-Age": "86400",
7535
- };
7536
-
7537
7600
  // Helper to create headers with CORS
7538
- function corsHeaders(contentType) {
7601
+ function corsHeaders(contentType, request, env) {
7539
7602
  return {
7540
7603
  "Content-Type": contentType,
7541
- ...CORS_HEADERS,
7604
+ ...runtimeCorsHeaders(request, env),
7542
7605
  };
7543
7606
  }
7544
7607
 
7545
- // Helper to add CORS headers to any Response without touching the body
7546
- function addCorsHeaders(response) {
7547
- // Skip WebSocket upgrade responses - they can't be wrapped
7548
- if (response.status === 101) {
7549
- return response;
7550
- }
7551
-
7552
- // Skip if already has CORS headers
7553
- if (response.headers.has("Access-Control-Allow-Origin")) {
7554
- return response;
7555
- }
7556
-
7557
- // Prefer mutating the original Response headers. Rebuilding a Response from
7558
- // response.headers can drop special headers such as Set-Cookie in Worker
7559
- // runtimes, even when the header is not visible through Headers.has().
7560
- try {
7561
- for (const [key, value] of Object.entries(CORS_HEADERS)) {
7562
- response.headers.set(key, value);
7563
- }
7564
- return response;
7565
- } catch {
7566
- // Some Responses, especially fetched upstream responses, have immutable
7567
- // headers. Fall back to wrapping those responses.
7568
- }
7569
-
7570
- // Create new headers with CORS added
7571
- const newHeaders = new Headers(response.headers);
7572
- for (const [key, value] of Object.entries(CORS_HEADERS)) {
7573
- newHeaders.set(key, value);
7574
- }
7575
-
7576
- // Return new Response with same body stream (not cloned, just transferred)
7577
- return new Response(response.body, {
7578
- status: response.status,
7579
- statusText: response.statusText,
7580
- headers: newHeaders,
7581
- });
7582
- }
7583
-
7584
7608
  export async function router(request, env) {
7585
7609
  const url = new URL(request.url);
7586
7610
  const pathname = url.pathname;
7587
7611
 
7588
7612
  // Handle CORS preflight requests
7589
7613
  if (request.method === "OPTIONS") {
7590
- return new Response(null, {
7591
- status: 204,
7592
- headers: CORS_HEADERS,
7593
- });
7614
+ return runtimePreflightResponse(request, env);
7615
+ }
7616
+
7617
+ // WebSockets do not use CORS. Reject foreign browser provenance before
7618
+ // route dispatch so a malicious page cannot open a local stream/bridge even
7619
+ // if a browser were to attach ambient cookies to the handshake.
7620
+ if (
7621
+ isTrustedLocalDevelopmentRequest(request, env) &&
7622
+ !isSameOriginBrowserRequest(request)
7623
+ ) {
7624
+ return Response.json(
7625
+ { error: "Cross-origin access is disabled for local development" },
7626
+ { status: 403, headers: { "Cache-Control": "no-store" } }
7627
+ );
7594
7628
  }
7595
7629
 
7596
7630
  const routePath = pathname || "/";
@@ -7638,13 +7672,13 @@ ${packedThreadRouteCode}
7638
7672
 
7639
7673
  // If requireAuth returns a Response, it's an error (401)
7640
7674
  if (authResult instanceof Response) {
7641
- return addCorsHeaders(authResult);
7675
+ return applyRuntimeCors(authResult, request, env);
7642
7676
  }
7643
7677
 
7644
7678
  authContext = authResult;
7645
7679
 
7646
7680
  if (isAdminOnlyApiRoute(routePath, request.method) && authContext.user.role !== 'admin') {
7647
- return addCorsHeaders(Response.json({ error: 'Forbidden: Admin access required' }, { status: 403 }));
7681
+ return applyRuntimeCors(Response.json({ error: 'Forbidden: Admin access required' }, { status: 403 }), request, env);
7648
7682
  }
7649
7683
 
7650
7684
  if (routePath.startsWith('/api/threads/')) {
@@ -7658,10 +7692,10 @@ ${packedThreadRouteCode}
7658
7692
  const agentBuilder = env.AGENT_BUILDER.get(agentBuilderId);
7659
7693
  const thread = await agentBuilder.getThread(threadId);
7660
7694
  if (!thread) {
7661
- return addCorsHeaders(Response.json({ error: \`Thread not found: \${threadId}\` }, { status: 404 }));
7695
+ return applyRuntimeCors(Response.json({ error: \`Thread not found: \${threadId}\` }, { status: 404 }), request, env);
7662
7696
  }
7663
7697
  if (!canAccessThread(authContext, thread)) {
7664
- return addCorsHeaders(Response.json({ error: "Forbidden: You don't have access to this thread" }, { status: 403 }));
7698
+ return applyRuntimeCors(Response.json({ error: "Forbidden: You don't have access to this thread" }, { status: 403 }), request, env);
7665
7699
  }
7666
7700
  threadAccess = { threadId, thread };
7667
7701
  }
@@ -7704,16 +7738,16 @@ ${packedThreadRouteCode}
7704
7738
  const result = await controller(context);
7705
7739
 
7706
7740
  if (result instanceof Response) {
7707
- return addCorsHeaders(result);
7741
+ return applyRuntimeCors(result, request, env);
7708
7742
  }
7709
7743
  if (typeof result === "string") {
7710
7744
  return new Response(result, {
7711
- headers: corsHeaders("text/plain"),
7745
+ headers: corsHeaders("text/plain", request, env),
7712
7746
  });
7713
7747
  }
7714
7748
  // JSON responses get CORS headers
7715
7749
  return new Response(JSON.stringify(result), {
7716
- headers: corsHeaders("application/json"),
7750
+ headers: corsHeaders("application/json", request, env),
7717
7751
  });
7718
7752
  }
7719
7753