@standardagents/builder 0.17.3 → 0.18.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.
@@ -3672,13 +3672,13 @@ var init_ToolExecutor = __esm({
3672
3672
  };
3673
3673
  }
3674
3674
  const reader = result.stream.getReader();
3675
- const decoder = new TextDecoder();
3675
+ const decoder2 = new TextDecoder();
3676
3676
  let textContent = "";
3677
3677
  try {
3678
3678
  while (true) {
3679
3679
  const { done, value } = await reader.read();
3680
3680
  if (done) break;
3681
- textContent += decoder.decode(value, { stream: true });
3681
+ textContent += decoder2.decode(value, { stream: true });
3682
3682
  }
3683
3683
  } finally {
3684
3684
  reader.releaseLock();
@@ -11628,8 +11628,8 @@ var init_ThreadStateImpl = __esm({
11628
11628
  } else {
11629
11629
  let base64Data;
11630
11630
  if (typeof data === "string") {
11631
- const encoder = new TextEncoder();
11632
- const bytes = encoder.encode(data);
11631
+ const encoder2 = new TextEncoder();
11632
+ const bytes = encoder2.encode(data);
11633
11633
  let binary = "";
11634
11634
  for (let i = 0; i < bytes.length; i++) {
11635
11635
  binary += String.fromCharCode(bytes[i]);
@@ -13703,12 +13703,12 @@ function parseToolArguments(argumentsJson) {
13703
13703
  }
13704
13704
  async function* parseChatSSEStream(stream, state) {
13705
13705
  const reader = stream.getReader();
13706
- const decoder = new TextDecoder();
13706
+ const decoder2 = new TextDecoder();
13707
13707
  let buffer = "";
13708
13708
  while (true) {
13709
13709
  const { value, done } = await reader.read();
13710
13710
  if (done) break;
13711
- buffer += decoder.decode(value, { stream: true });
13711
+ buffer += decoder2.decode(value, { stream: true });
13712
13712
  while (true) {
13713
13713
  const separatorIndex = buffer.indexOf("\n\n");
13714
13714
  if (separatorIndex === -1) break;
@@ -15086,13 +15086,13 @@ async function* parseChatSSEStream2(response, state) {
15086
15086
  if (!reader) {
15087
15087
  throw new Error("No response body");
15088
15088
  }
15089
- const decoder = new TextDecoder();
15089
+ const decoder2 = new TextDecoder();
15090
15090
  let buffer = "";
15091
15091
  try {
15092
15092
  while (true) {
15093
15093
  const { done, value } = await reader.read();
15094
15094
  if (done) break;
15095
- buffer += decoder.decode(value, { stream: true });
15095
+ buffer += decoder2.decode(value, { stream: true });
15096
15096
  const lines = buffer.split("\n");
15097
15097
  buffer = lines.pop() || "";
15098
15098
  for (const line of lines) {
@@ -25381,12 +25381,12 @@ function concatBytes(buffers) {
25381
25381
  return output;
25382
25382
  }
25383
25383
  function encodeUTF8(str) {
25384
- let encoder;
25385
- return (encodeUTF8_ !== null && encodeUTF8_ !== void 0 ? encodeUTF8_ : (encoder = new globalThis.TextEncoder(), encodeUTF8_ = encoder.encode.bind(encoder)))(str);
25384
+ let encoder2;
25385
+ return (encodeUTF8_ !== null && encodeUTF8_ !== void 0 ? encodeUTF8_ : (encoder2 = new globalThis.TextEncoder(), encodeUTF8_ = encoder2.encode.bind(encoder2)))(str);
25386
25386
  }
25387
25387
  function decodeUTF8(bytes) {
25388
- let decoder;
25389
- return (decodeUTF8_ !== null && decodeUTF8_ !== void 0 ? decodeUTF8_ : (decoder = new globalThis.TextDecoder(), decodeUTF8_ = decoder.decode.bind(decoder)))(bytes);
25388
+ let decoder2;
25389
+ return (decodeUTF8_ !== null && decodeUTF8_ !== void 0 ? decodeUTF8_ : (decoder2 = new globalThis.TextDecoder(), decodeUTF8_ = decoder2.decode.bind(decoder2)))(bytes);
25390
25390
  }
25391
25391
  function findNewlineIndex(buffer, startIndex) {
25392
25392
  const newline = 10;
@@ -29093,7 +29093,7 @@ var init_web = __esm({
29093
29093
  return __asyncGenerator(this, arguments, function* processStreamResponse_1() {
29094
29094
  var _a16;
29095
29095
  const reader = (_a16 = response === null || response === void 0 ? void 0 : response.body) === null || _a16 === void 0 ? void 0 : _a16.getReader();
29096
- const decoder = new TextDecoder("utf-8");
29096
+ const decoder2 = new TextDecoder("utf-8");
29097
29097
  if (!reader) {
29098
29098
  throw new Error("Response body is empty");
29099
29099
  }
@@ -29109,7 +29109,7 @@ var init_web = __esm({
29109
29109
  }
29110
29110
  break;
29111
29111
  }
29112
- const chunkString = decoder.decode(value, { stream: true });
29112
+ const chunkString = decoder2.decode(value, { stream: true });
29113
29113
  try {
29114
29114
  const chunkJson = JSON.parse(chunkString);
29115
29115
  if ("error" in chunkJson) {
@@ -35732,12 +35732,12 @@ function concatBytes2(buffers) {
35732
35732
  return output;
35733
35733
  }
35734
35734
  function encodeUTF82(str) {
35735
- let encoder;
35736
- return (encodeUTF8_2 ?? (encoder = new globalThis.TextEncoder(), encodeUTF8_2 = encoder.encode.bind(encoder)))(str);
35735
+ let encoder2;
35736
+ return (encodeUTF8_2 ?? (encoder2 = new globalThis.TextEncoder(), encodeUTF8_2 = encoder2.encode.bind(encoder2)))(str);
35737
35737
  }
35738
35738
  function decodeUTF82(bytes) {
35739
- let decoder;
35740
- return (decodeUTF8_2 ?? (decoder = new globalThis.TextDecoder(), decodeUTF8_2 = decoder.decode.bind(decoder)))(bytes);
35739
+ let decoder2;
35740
+ return (decodeUTF8_2 ?? (decoder2 = new globalThis.TextDecoder(), decodeUTF8_2 = decoder2.decode.bind(decoder2)))(bytes);
35741
35741
  }
35742
35742
  var encodeUTF8_2, decodeUTF8_2;
35743
35743
  var init_bytes = __esm({
@@ -50030,8 +50030,8 @@ async function oAuthCreateSHA256CodeChallenge(params = {}) {
50030
50030
  };
50031
50031
  }
50032
50032
  const { codeVerifier = generateCodeVerifier() } = parsedParams.data;
50033
- const encoder = new TextEncoder();
50034
- const data = encoder.encode(codeVerifier);
50033
+ const encoder2 = new TextEncoder();
50034
+ const data = encoder2.encode(codeVerifier);
50035
50035
  const hash = await crypto.subtle.digest("SHA-256", data);
50036
50036
  const hashArray = new Uint8Array(hash);
50037
50037
  const codeChallenge = arrayBufferToBase64Url(hashArray);
@@ -51840,13 +51840,13 @@ async function* parseChatSSEStream3(response, state) {
51840
51840
  if (!reader) {
51841
51841
  throw new Error("No response body");
51842
51842
  }
51843
- const decoder = new TextDecoder();
51843
+ const decoder2 = new TextDecoder();
51844
51844
  let buffer = "";
51845
51845
  try {
51846
51846
  while (true) {
51847
51847
  const { done, value } = await reader.read();
51848
51848
  if (done) break;
51849
- buffer += decoder.decode(value, { stream: true });
51849
+ buffer += decoder2.decode(value, { stream: true });
51850
51850
  const lines = buffer.split("\n");
51851
51851
  buffer = lines.pop() || "";
51852
51852
  for (const line of lines) {
@@ -52782,13 +52782,13 @@ async function* parseSSEStream(response, state) {
52782
52782
  if (!reader) {
52783
52783
  throw new Error("No response body");
52784
52784
  }
52785
- const decoder = new TextDecoder();
52785
+ const decoder2 = new TextDecoder();
52786
52786
  let buffer = "";
52787
52787
  try {
52788
52788
  while (true) {
52789
52789
  const { done, value } = await reader.read();
52790
52790
  if (done) break;
52791
- buffer += decoder.decode(value, { stream: true });
52791
+ buffer += decoder2.decode(value, { stream: true });
52792
52792
  const lines = buffer.split("\n");
52793
52793
  buffer = lines.pop() || "";
52794
52794
  for (const line of lines) {
@@ -63020,8 +63020,8 @@ function generateApiKey() {
63020
63020
  return `agtbldr_${generateSecureToken(32)}`;
63021
63021
  }
63022
63022
  async function hashPassword(password) {
63023
- const encoder = new TextEncoder();
63024
- const data = encoder.encode(password);
63023
+ const encoder2 = new TextEncoder();
63024
+ const data = encoder2.encode(password);
63025
63025
  const salt = crypto.getRandomValues(new Uint8Array(16));
63026
63026
  const keyMaterial = await crypto.subtle.importKey(
63027
63027
  "raw",
@@ -63051,8 +63051,8 @@ async function verifyPassword(password, hash) {
63051
63051
  const combined = base64ToBuffer(hash);
63052
63052
  const salt = combined.slice(0, 16);
63053
63053
  const storedHash = combined.slice(16);
63054
- const encoder = new TextEncoder();
63055
- const data = encoder.encode(password);
63054
+ const encoder2 = new TextEncoder();
63055
+ const data = encoder2.encode(password);
63056
63056
  const keyMaterial = await crypto.subtle.importKey(
63057
63057
  "raw",
63058
63058
  data,
@@ -63087,8 +63087,8 @@ async function verifyPassword(password, hash) {
63087
63087
  }
63088
63088
  }
63089
63089
  async function hashToken(token) {
63090
- const encoder = new TextEncoder();
63091
- const data = encoder.encode(token);
63090
+ const encoder2 = new TextEncoder();
63091
+ const data = encoder2.encode(token);
63092
63092
  const hashBuffer = await crypto.subtle.digest("SHA-256", data);
63093
63093
  const hashArray = new Uint8Array(hashBuffer);
63094
63094
  return Array.from(hashArray, (byte) => byte.toString(16).padStart(2, "0")).join("");
@@ -63128,11 +63128,11 @@ function isValidUserToken(token) {
63128
63128
  return token.startsWith("agtuser_") && token.length > 10;
63129
63129
  }
63130
63130
  function isValidApiKey(key) {
63131
- return key.startsWith("agtbldr_") && key.length > 10;
63131
+ return key.startsWith("agtbldr_") && key.length > 10 || key.startsWith("sak_live_") && key.length > 10;
63132
63132
  }
63133
63133
  async function signToken(payload, encryptionKey) {
63134
- const encoder = new TextEncoder();
63135
- const keyData = encoder.encode(encryptionKey);
63134
+ const encoder2 = new TextEncoder();
63135
+ const keyData = encoder2.encode(encryptionKey);
63136
63136
  const cryptoKey = await crypto.subtle.importKey(
63137
63137
  "raw",
63138
63138
  keyData,
@@ -63140,7 +63140,7 @@ async function signToken(payload, encryptionKey) {
63140
63140
  false,
63141
63141
  ["sign"]
63142
63142
  );
63143
- const payloadData = encoder.encode(payload);
63143
+ const payloadData = encoder2.encode(payload);
63144
63144
  const signature = await crypto.subtle.sign("HMAC", cryptoKey, payloadData);
63145
63145
  const payloadB64 = bufferToBase64(new Uint8Array(payloadData));
63146
63146
  const signatureB64 = bufferToBase64(new Uint8Array(signature));
@@ -63153,8 +63153,8 @@ async function verifySignedToken(signedToken, encryptionKey) {
63153
63153
  return null;
63154
63154
  }
63155
63155
  const [payloadB64, signatureB64] = parts;
63156
- const encoder = new TextEncoder();
63157
- const keyData = encoder.encode(encryptionKey);
63156
+ const encoder2 = new TextEncoder();
63157
+ const keyData = encoder2.encode(encryptionKey);
63158
63158
  const cryptoKey = await crypto.subtle.importKey(
63159
63159
  "raw",
63160
63160
  keyData,
@@ -63168,8 +63168,8 @@ async function verifySignedToken(signedToken, encryptionKey) {
63168
63168
  if (!isValid) {
63169
63169
  return null;
63170
63170
  }
63171
- const decoder = new TextDecoder();
63172
- return decoder.decode(payloadData);
63171
+ const decoder2 = new TextDecoder();
63172
+ return decoder2.decode(payloadData);
63173
63173
  } catch (error) {
63174
63174
  console.error("Error verifying signed token:", error);
63175
63175
  return null;
@@ -63281,7 +63281,11 @@ async function authenticate(request, env2) {
63281
63281
  user: {
63282
63282
  id: user.id,
63283
63283
  username: user.username,
63284
- role: user.role
63284
+ role: user.role,
63285
+ platform_user_id: user.platform_user_id ?? null,
63286
+ email: user.email ?? null,
63287
+ display_name: user.display_name ?? null,
63288
+ avatar_url: user.avatar_url ?? null
63285
63289
  },
63286
63290
  authType: "session"
63287
63291
  };
@@ -63299,7 +63303,11 @@ async function authenticate(request, env2) {
63299
63303
  user: {
63300
63304
  id: user.id,
63301
63305
  username: user.username,
63302
- role: user.role
63306
+ role: user.role,
63307
+ platform_user_id: user.platform_user_id ?? null,
63308
+ email: user.email ?? null,
63309
+ display_name: user.display_name ?? null,
63310
+ avatar_url: user.avatar_url ?? null
63303
63311
  },
63304
63312
  authType: "api_key"
63305
63313
  };
@@ -63335,88 +63343,6 @@ async function requireAdmin(request, env2) {
63335
63343
  return result;
63336
63344
  }
63337
63345
 
63338
- // src/api/api-keys/index.get.ts
63339
- var index_get_default = defineController2(async ({ req, env: env2 }) => {
63340
- try {
63341
- const authResult = await requireAuth(req, env2);
63342
- if (authResult instanceof Response) {
63343
- return authResult;
63344
- }
63345
- if (authResult.authType === "super_admin") {
63346
- return Response.json({ keys: [], message: "Super admin has no API keys. Create a user account to manage API keys." });
63347
- }
63348
- const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
63349
- const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
63350
- const keys = await agentBuilder.listApiKeys(authResult.user.id);
63351
- return Response.json({ keys });
63352
- } catch (error) {
63353
- console.error("List API keys error:", error);
63354
- return Response.json(
63355
- { error: error.message || "Failed to list API keys" },
63356
- { status: 500 }
63357
- );
63358
- }
63359
- });
63360
-
63361
- // src/api/api-keys/index.post.ts
63362
- var index_post_default2 = defineController2(async ({ req, env: env2 }) => {
63363
- try {
63364
- const authResult = await requireAuth(req, env2);
63365
- if (authResult instanceof Response) {
63366
- return authResult;
63367
- }
63368
- if (authResult.authType === "super_admin") {
63369
- return Response.json(
63370
- { error: "Super admin cannot create API keys. Please create a user account first." },
63371
- { status: 400 }
63372
- );
63373
- }
63374
- const body = await req.json();
63375
- const { name: name15 } = body;
63376
- if (!name15 || typeof name15 !== "string") {
63377
- return Response.json(
63378
- { error: "Name is required" },
63379
- { status: 400 }
63380
- );
63381
- }
63382
- if (name15.length < 1 || name15.length > 100) {
63383
- return Response.json(
63384
- { error: "Name must be between 1 and 100 characters" },
63385
- { status: 400 }
63386
- );
63387
- }
63388
- const apiKey = generateApiKey();
63389
- const keyHash = await hashToken(apiKey);
63390
- const keyPrefix = getTokenPrefix(apiKey);
63391
- const lastFive = getLastChars(apiKey, 5);
63392
- const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
63393
- const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
63394
- const id = await agentBuilder.createApiKey({
63395
- name: name15,
63396
- key_hash: keyHash,
63397
- key_prefix: keyPrefix,
63398
- last_five: lastFive,
63399
- user_id: authResult.user.id
63400
- });
63401
- const now = Math.floor(Date.now() / 1e3);
63402
- return Response.json({
63403
- key: apiKey,
63404
- // Only returned once on creation
63405
- id,
63406
- name: name15,
63407
- key_prefix: keyPrefix,
63408
- last_five: lastFive,
63409
- created_at: now
63410
- }, { status: 201 });
63411
- } catch (error) {
63412
- console.error("Create API key error:", error);
63413
- return Response.json(
63414
- { error: error.message || "Failed to create API key" },
63415
- { status: 500 }
63416
- );
63417
- }
63418
- });
63419
-
63420
63346
  // src/utils/platform-auth.ts
63421
63347
  var FALLBACK_PLATFORM_ORIGIN = "https://platform.standardagents.ai";
63422
63348
  var SESSION_TTL_SECONDS = 30 * 24 * 60 * 60;
@@ -63438,21 +63364,25 @@ function platformEndpoint(env2) {
63438
63364
  }
63439
63365
  return FALLBACK_PLATFORM_ORIGIN;
63440
63366
  }
63367
+ function hostedInstanceRedirectId(req, env2) {
63368
+ const configured = env2.STANDARD_AGENTS_PROJECT_ID || env2.STANDARD_AGENTS_INSTANCE_ID || env2.STANDARD_AGENTS_INSTANCE_SUBDOMAIN;
63369
+ if (typeof configured === "string" && configured.trim()) {
63370
+ return configured.trim();
63371
+ }
63372
+ return new URL(req.url).hostname;
63373
+ }
63374
+ function platformLoginUrl(req, env2, returnTo) {
63375
+ const url = new URL("/login", platformEndpoint(env2));
63376
+ url.searchParams.set("redirect", hostedInstanceRedirectId(req, env2));
63377
+ const reqUrl = new URL(req.url);
63378
+ const next = returnTo && returnTo.startsWith("/") && !returnTo.startsWith("//") ? returnTo : `${reqUrl.pathname}${reqUrl.search}`;
63379
+ url.searchParams.set("return_to", next || "/");
63380
+ return url.toString();
63381
+ }
63441
63382
  function sanitizeUsername(input) {
63442
63383
  const normalized = input.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 50);
63443
63384
  return normalized || "standard-agents";
63444
63385
  }
63445
- async function fallbackAccountForToken(token) {
63446
- const tokenHash = await hashToken(token);
63447
- const suffix = tokenHash.slice(0, 12);
63448
- return {
63449
- id: `platform-token-${suffix}`,
63450
- name: "Standard Agents",
63451
- slug: `standard-agents-${suffix}`,
63452
- tier: void 0,
63453
- status: "token-present"
63454
- };
63455
- }
63456
63386
  function normalizeAccount(payload) {
63457
63387
  const account = payload.account;
63458
63388
  if (!account) return null;
@@ -63486,21 +63416,70 @@ async function fetchPlatformAccount(endpoint, token) {
63486
63416
  return null;
63487
63417
  }
63488
63418
  }
63419
+ function normalizeLocalBootstrap(payload, endpoint) {
63420
+ const projectId = typeof payload.project?.id === "string" ? payload.project.id : null;
63421
+ const platformUserId = typeof payload.user?.platform_user_id === "string" ? payload.user.platform_user_id : typeof payload.user?.id === "string" ? payload.user.id : null;
63422
+ const role = payload.user?.role === "user" ? "user" : payload.user?.role === "admin" ? "admin" : null;
63423
+ if (!projectId || !platformUserId || !role) return null;
63424
+ const username = typeof payload.user?.username === "string" && payload.user.username.trim() ? sanitizeUsername(payload.user.username) : sanitizeUsername(
63425
+ typeof payload.user?.email === "string" && payload.user.email.includes("@") ? payload.user.email.split("@")[0] : `sa-${platformUserId.slice(0, 12)}`
63426
+ );
63427
+ const accountId = typeof payload.project?.account_id === "string" ? payload.project.account_id : projectId;
63428
+ const accountSlug = typeof payload.project?.subdomain === "string" && payload.project.subdomain.trim() ? payload.project.subdomain.trim() : projectId;
63429
+ return {
63430
+ connected: true,
63431
+ verified: true,
63432
+ account: {
63433
+ id: accountId,
63434
+ name: accountSlug,
63435
+ slug: accountSlug,
63436
+ status: "active"
63437
+ },
63438
+ user: {
63439
+ id: platformUserId,
63440
+ username,
63441
+ role,
63442
+ email: typeof payload.user?.email === "string" ? payload.user.email : null,
63443
+ display_name: typeof payload.user?.display_name === "string" ? payload.user.display_name : null,
63444
+ avatar_url: typeof payload.user?.avatar_url === "string" ? payload.user.avatar_url : null,
63445
+ source: "standard_agents"
63446
+ },
63447
+ platformEndpoint: endpoint
63448
+ };
63449
+ }
63450
+ async function fetchLocalBootstrapIdentity(endpoint, token) {
63451
+ const response = await fetch(`${endpoint}/auth/local-bootstrap`, {
63452
+ headers: {
63453
+ Authorization: `Bearer ${token}`
63454
+ }
63455
+ });
63456
+ if (!response.ok) {
63457
+ return null;
63458
+ }
63459
+ const data = await response.json().catch(() => null);
63460
+ return data ? normalizeLocalBootstrap(data, endpoint) : null;
63461
+ }
63489
63462
  async function getPlatformIdentity(env2) {
63490
63463
  const token = platformApiKey(env2);
63491
63464
  if (!token) {
63492
63465
  return null;
63493
63466
  }
63494
63467
  const endpoint = platformEndpoint(env2);
63468
+ const bootstrapIdentity = await fetchLocalBootstrapIdentity(endpoint, token).catch(() => null);
63469
+ if (bootstrapIdentity) {
63470
+ return bootstrapIdentity;
63471
+ }
63495
63472
  const verifiedAccount = await fetchPlatformAccount(endpoint, token);
63496
- const account = verifiedAccount ?? await fallbackAccountForToken(token);
63497
- const username = sanitizeUsername(account.slug);
63473
+ if (!verifiedAccount) {
63474
+ return null;
63475
+ }
63476
+ const username = sanitizeUsername(verifiedAccount.slug);
63498
63477
  return {
63499
63478
  connected: true,
63500
63479
  verified: verifiedAccount !== null,
63501
- account,
63480
+ account: verifiedAccount,
63502
63481
  user: {
63503
- id: account.id,
63482
+ id: verifiedAccount.id,
63504
63483
  username,
63505
63484
  role: "admin",
63506
63485
  source: "standard_agents"
@@ -63508,21 +63487,21 @@ async function getPlatformIdentity(env2) {
63508
63487
  platformEndpoint: endpoint
63509
63488
  };
63510
63489
  }
63511
- async function mintLocalSessionForPlatformUser(env2, platformUserId) {
63490
+ async function mintLocalSessionForPlatformUser(env2, platformUser) {
63512
63491
  const namespace = env2.AGENT_BUILDER;
63513
63492
  if (!namespace || typeof namespace.idFromName !== "function" || typeof namespace.get !== "function") {
63514
63493
  throw new Error("Server misconfigured: AGENT_BUILDER Durable Object binding is required for platform auth");
63515
63494
  }
63516
63495
  const agentBuilder = namespace.get(namespace.idFromName("singleton"));
63517
- const username = sanitizeUsername(`sa-${platformUserId}`);
63518
- let user = await agentBuilder.getUserByUsername(username);
63519
- if (!user) {
63520
- user = await agentBuilder.createUser({
63521
- username,
63522
- password_hash: await hashPassword(crypto.randomUUID()),
63523
- role: "admin"
63524
- });
63525
- }
63496
+ const profile = typeof platformUser === "string" ? { platform_user_id: platformUser, username: `sa-${platformUser.slice(0, 12)}`, role: "admin" } : platformUser;
63497
+ const user = await agentBuilder.upsertPlatformReplicaUser({
63498
+ platform_user_id: profile.platform_user_id,
63499
+ username: profile.username ?? null,
63500
+ display_name: profile.display_name ?? null,
63501
+ email: profile.email ?? null,
63502
+ avatar_url: profile.avatar_url ?? null,
63503
+ role: profile.role ?? "admin"
63504
+ });
63526
63505
  const token = generateUserToken();
63527
63506
  const tokenHash = await hashToken(token);
63528
63507
  const expiresAt = Math.floor(Date.now() / 1e3) + SESSION_TTL_SECONDS;
@@ -63533,31 +63512,29 @@ async function createPlatformLocalSession(env2) {
63533
63512
  if (isPlatformHosted(env2)) {
63534
63513
  return null;
63535
63514
  }
63536
- const identity = await getPlatformIdentity(env2);
63537
- if (!identity) {
63515
+ const apiKey = platformApiKey(env2);
63516
+ if (!apiKey) {
63538
63517
  return null;
63539
63518
  }
63519
+ const endpoint = platformEndpoint(env2);
63520
+ const identity = await fetchLocalBootstrapIdentity(endpoint, apiKey).catch(() => null);
63521
+ if (!identity) {
63522
+ throw new Error("STANDARD_AGENTS_API_KEY could not be resolved to one active user-instance membership.");
63523
+ }
63540
63524
  const agentBuilderNamespace = env2.AGENT_BUILDER;
63541
63525
  if (!agentBuilderNamespace || typeof agentBuilderNamespace.idFromName !== "function" || typeof agentBuilderNamespace.get !== "function") {
63542
63526
  throw new Error("Server misconfigured: AGENT_BUILDER Durable Object binding is required for platform auth");
63543
63527
  }
63544
63528
  const agentBuilderId = agentBuilderNamespace.idFromName("singleton");
63545
63529
  const agentBuilder = agentBuilderNamespace.get(agentBuilderId);
63546
- const username = identity.user.username;
63547
- let user = await agentBuilder.getUserByUsername(username);
63548
- if (!user) {
63549
- const legacyUsername = sanitizeUsername(`standard-agents-${identity.account.slug}`);
63550
- const legacyUser = legacyUsername !== username ? await agentBuilder.getUserByUsername(legacyUsername) : null;
63551
- if (legacyUser) {
63552
- user = await agentBuilder.updateUser(legacyUser.id, { username }) ?? legacyUser;
63553
- } else {
63554
- user = await agentBuilder.createUser({
63555
- username,
63556
- password_hash: await hashPassword(crypto.randomUUID()),
63557
- role: "admin"
63558
- });
63559
- }
63560
- }
63530
+ const user = await agentBuilder.upsertPlatformReplicaUser({
63531
+ platform_user_id: identity.user.id,
63532
+ username: identity.user.username,
63533
+ display_name: identity.user.display_name ?? null,
63534
+ email: identity.user.email ?? null,
63535
+ avatar_url: identity.user.avatar_url ?? null,
63536
+ role: identity.user.role
63537
+ });
63561
63538
  const token = generateUserToken();
63562
63539
  const tokenHash = await hashToken(token);
63563
63540
  const expiresAt = Math.floor(Date.now() / 1e3) + SESSION_TTL_SECONDS;
@@ -63577,6 +63554,94 @@ async function createPlatformLocalSession(env2) {
63577
63554
  platform: identity
63578
63555
  };
63579
63556
  }
63557
+
63558
+ // src/api/api-keys/index.get.ts
63559
+ var index_get_default = defineController2(async ({ req, env: env2 }) => {
63560
+ try {
63561
+ if (isPlatformHosted(env2)) {
63562
+ return Response.json({ error: "API keys are managed in the Standard Agents platform." }, { status: 410 });
63563
+ }
63564
+ const authResult = await requireAuth(req, env2);
63565
+ if (authResult instanceof Response) {
63566
+ return authResult;
63567
+ }
63568
+ if (authResult.authType === "super_admin") {
63569
+ return Response.json({ keys: [], message: "Super admin has no API keys. Create a user account to manage API keys." });
63570
+ }
63571
+ const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
63572
+ const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
63573
+ const keys = await agentBuilder.listApiKeys(authResult.user.id);
63574
+ return Response.json({ keys });
63575
+ } catch (error) {
63576
+ console.error("List API keys error:", error);
63577
+ return Response.json(
63578
+ { error: error.message || "Failed to list API keys" },
63579
+ { status: 500 }
63580
+ );
63581
+ }
63582
+ });
63583
+
63584
+ // src/api/api-keys/index.post.ts
63585
+ var index_post_default2 = defineController2(async ({ req, env: env2 }) => {
63586
+ try {
63587
+ if (isPlatformHosted(env2)) {
63588
+ return Response.json({ error: "API keys are managed in the Standard Agents platform." }, { status: 410 });
63589
+ }
63590
+ const authResult = await requireAuth(req, env2);
63591
+ if (authResult instanceof Response) {
63592
+ return authResult;
63593
+ }
63594
+ if (authResult.authType === "super_admin") {
63595
+ return Response.json(
63596
+ { error: "Super admin cannot create API keys. Please create a user account first." },
63597
+ { status: 400 }
63598
+ );
63599
+ }
63600
+ const body = await req.json();
63601
+ const { name: name15 } = body;
63602
+ if (!name15 || typeof name15 !== "string") {
63603
+ return Response.json(
63604
+ { error: "Name is required" },
63605
+ { status: 400 }
63606
+ );
63607
+ }
63608
+ if (name15.length < 1 || name15.length > 100) {
63609
+ return Response.json(
63610
+ { error: "Name must be between 1 and 100 characters" },
63611
+ { status: 400 }
63612
+ );
63613
+ }
63614
+ const apiKey = generateApiKey();
63615
+ const keyHash = await hashToken(apiKey);
63616
+ const keyPrefix = getTokenPrefix(apiKey);
63617
+ const lastFive = getLastChars(apiKey, 5);
63618
+ const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
63619
+ const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
63620
+ const id = await agentBuilder.createApiKey({
63621
+ name: name15,
63622
+ key_hash: keyHash,
63623
+ key_prefix: keyPrefix,
63624
+ last_five: lastFive,
63625
+ user_id: authResult.user.id
63626
+ });
63627
+ const now = Math.floor(Date.now() / 1e3);
63628
+ return Response.json({
63629
+ key: apiKey,
63630
+ // Only returned once on creation
63631
+ id,
63632
+ name: name15,
63633
+ key_prefix: keyPrefix,
63634
+ last_five: lastFive,
63635
+ created_at: now
63636
+ }, { status: 201 });
63637
+ } catch (error) {
63638
+ console.error("Create API key error:", error);
63639
+ return Response.json(
63640
+ { error: error.message || "Failed to create API key" },
63641
+ { status: 500 }
63642
+ );
63643
+ }
63644
+ });
63580
63645
  var STATE_RELATIVE_PATH = path5__default.join(".agents", "bootstrap-session.json");
63581
63646
  var PROJECT_ROOT_ENV_KEYS = ["INIT_CWD", "PWD", "npm_config_local_prefix"];
63582
63647
  function readEnvString(env2, key) {
@@ -64669,6 +64734,9 @@ var tools_get_default = defineController2(async ({ url, tools, prompts, promptNa
64669
64734
  // src/api/users/index.get.ts
64670
64735
  var index_get_default2 = defineController2(async ({ req, env: env2 }) => {
64671
64736
  try {
64737
+ if (isPlatformHosted(env2)) {
64738
+ return Response.json({ error: "Users are managed in the Standard Agents platform." }, { status: 410 });
64739
+ }
64672
64740
  const authResult = await requireAdmin(req, env2);
64673
64741
  if (authResult instanceof Response) {
64674
64742
  return authResult;
@@ -64700,6 +64768,9 @@ var index_get_default2 = defineController2(async ({ req, env: env2 }) => {
64700
64768
  var VALID_ROLES = ["admin", "user"];
64701
64769
  var index_post_default4 = defineController2(async ({ req, env: env2 }) => {
64702
64770
  try {
64771
+ if (isPlatformHosted(env2)) {
64772
+ return Response.json({ error: "Users are managed in the Standard Agents platform." }, { status: 410 });
64773
+ }
64703
64774
  const authResult = await requireAdmin(req, env2);
64704
64775
  if (authResult instanceof Response) {
64705
64776
  return authResult;
@@ -64883,6 +64954,9 @@ var name_get_default = defineController2(async ({ params, agents, prompts, promp
64883
64954
  // src/api/api-keys/[id].delete.ts
64884
64955
  var id_delete_default = defineController2(async ({ req, env: env2, params }) => {
64885
64956
  try {
64957
+ if (isPlatformHosted(env2)) {
64958
+ return Response.json({ error: "API keys are managed in the Standard Agents platform." }, { status: 410 });
64959
+ }
64886
64960
  const authResult = await requireAuth(req, env2);
64887
64961
  if (authResult instanceof Response) {
64888
64962
  return authResult;
@@ -65600,6 +65674,9 @@ var index_post_default6 = defineController2(async ({ req }) => {
65600
65674
  // src/api/users/[id].delete.ts
65601
65675
  var id_delete_default3 = defineController2(async ({ req, env: env2, params }) => {
65602
65676
  try {
65677
+ if (isPlatformHosted(env2)) {
65678
+ return Response.json({ error: "Users are managed in the Standard Agents platform." }, { status: 410 });
65679
+ }
65603
65680
  const authResult = await requireAdmin(req, env2);
65604
65681
  if (authResult instanceof Response) {
65605
65682
  return authResult;
@@ -65628,6 +65705,9 @@ var id_delete_default3 = defineController2(async ({ req, env: env2, params }) =>
65628
65705
  // src/api/users/[id].put.ts
65629
65706
  var id_put_default = defineController2(async ({ req, env: env2, params }) => {
65630
65707
  try {
65708
+ if (isPlatformHosted(env2)) {
65709
+ return Response.json({ error: "Users are managed in the Standard Agents platform." }, { status: 410 });
65710
+ }
65631
65711
  const authResult = await requireAdmin(req, env2);
65632
65712
  if (authResult instanceof Response) {
65633
65713
  return authResult;
@@ -65661,7 +65741,7 @@ var id_put_default = defineController2(async ({ req, env: env2, params }) => {
65661
65741
  updateParams.password_hash = await hashPassword(password);
65662
65742
  }
65663
65743
  if (role) {
65664
- updateParams.role = role;
65744
+ updateParams.role = role === "user" ? "user" : "admin";
65665
65745
  }
65666
65746
  const updatedUser = await agentBuilder.updateUser(id, updateParams);
65667
65747
  return Response.json({
@@ -65683,104 +65763,18 @@ var id_put_default = defineController2(async ({ req, env: env2, params }) => {
65683
65763
  });
65684
65764
 
65685
65765
  // src/api/auth/bootstrap.post.ts
65686
- function deriveManagedUsername(platformUserId) {
65687
- return `sa-${platformUserId}`;
65688
- }
65689
- function uniqueEndpoints(preferred, candidates) {
65690
- return Array.from(new Set([preferred, ...candidates].filter(Boolean)));
65691
- }
65692
- var bootstrap_post_default = defineController2(async ({ req, env: env2 }) => {
65766
+ var bootstrap_post_default = defineController2(async ({ env: env2 }) => {
65693
65767
  try {
65694
65768
  const platformTokenSession = await createPlatformLocalSession(env2);
65695
- if (platformTokenSession) {
65696
- return Response.json(platformTokenSession);
65769
+ if (!platformTokenSession) {
65770
+ return new Response(null, { status: 204 });
65697
65771
  }
65772
+ return Response.json(platformTokenSession);
65698
65773
  } catch (error) {
65699
- console.error("Platform auth bootstrap error:", error);
65700
- return Response.json(
65701
- { error: error instanceof Error ? error.message : "Failed to bootstrap platform auth" },
65702
- { status: 500 }
65703
- );
65704
- }
65705
- const bootstrap = findLocalBootstrapSession(void 0, env2);
65706
- const bootstrapState = bootstrap?.session;
65707
- if (!bootstrapState?.session_cookie) {
65708
- return new Response(null, { status: 204 });
65774
+ const message = error instanceof Error ? error.message : "Failed to bootstrap platform auth";
65775
+ const status = message.includes("STANDARD_AGENTS_API_KEY") ? 401 : 502;
65776
+ return Response.json({ error: message }, { status });
65709
65777
  }
65710
- const endpoints = uniqueEndpoints(
65711
- bootstrapState.endpoint,
65712
- resolvePlatformEndpointCandidates(req, env2)
65713
- );
65714
- let platformUser = null;
65715
- for (const endpoint of endpoints) {
65716
- try {
65717
- const response = await fetch(`${endpoint}/auth/session`, {
65718
- method: "GET",
65719
- headers: {
65720
- Cookie: bootstrapState.session_cookie
65721
- }
65722
- });
65723
- if (response.status === 401) {
65724
- return Response.json(
65725
- { error: "Stored Standard Agents session is no longer valid. Run `agents login` again." },
65726
- { status: 401 }
65727
- );
65728
- }
65729
- if (!response.ok) {
65730
- continue;
65731
- }
65732
- const payload = await response.json().catch(() => ({}));
65733
- platformUser = payload.user ?? null;
65734
- break;
65735
- } catch {
65736
- continue;
65737
- }
65738
- }
65739
- const fallbackPlatformUserId = bootstrapState.user?.id;
65740
- const platformUserId = platformUser?.id ?? fallbackPlatformUserId;
65741
- if (!platformUserId) {
65742
- return Response.json(
65743
- { error: "Bad Gateway: platform API unreachable" },
65744
- { status: 502 }
65745
- );
65746
- }
65747
- const username = deriveManagedUsername(platformUserId);
65748
- if (!env2.AGENT_BUILDER || typeof env2.AGENT_BUILDER.idFromName !== "function") {
65749
- return Response.json(
65750
- { error: "Server misconfigured: AGENT_BUILDER Durable Object binding is required for platform auth" },
65751
- { status: 500 }
65752
- );
65753
- }
65754
- const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
65755
- const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
65756
- let user = await agentBuilder.getUserByUsername(username);
65757
- if (!user) {
65758
- user = await agentBuilder.createUser({
65759
- username,
65760
- password_hash: await hashPassword(crypto.randomUUID()),
65761
- role: "admin"
65762
- });
65763
- }
65764
- const token = generateUserToken();
65765
- const tokenHash = await hashToken(token);
65766
- const expiresAt = Math.floor(Date.now() / 1e3) + 30 * 24 * 60 * 60;
65767
- await agentBuilder.createSession({
65768
- user_id: user.id,
65769
- token_hash: tokenHash,
65770
- expires_at: expiresAt
65771
- });
65772
- return Response.json({
65773
- token,
65774
- user: {
65775
- id: user.id,
65776
- username: user.username,
65777
- role: user.role
65778
- },
65779
- platform_user: {
65780
- id: platformUserId,
65781
- email: platformUser?.email ?? bootstrapState.user?.email
65782
- }
65783
- });
65784
65778
  });
65785
65779
 
65786
65780
  // src/api/auth/config.get.ts
@@ -65791,7 +65785,7 @@ var config_get_default2 = defineController2(async ({ req, env: env2 }) => {
65791
65785
  const platformConnected = hasPlatformApiKey(env2) || !!findLocalBootstrapSession(void 0, env2);
65792
65786
  const localPassword = typeof env2.SUPER_ADMIN_PASSWORD === "string" && env2.SUPER_ADMIN_PASSWORD.length > 0;
65793
65787
  const hosted = isPlatformHosted(env2);
65794
- const standardAgentsLogin = hosted && typeof env2.STANDARD_AGENTS_OAUTH_CLIENT_ID === "string" && env2.STANDARD_AGENTS_OAUTH_CLIENT_ID.trim() !== "";
65788
+ const standardAgentsLogin = hosted;
65795
65789
  return {
65796
65790
  github: githubConfigured,
65797
65791
  google: googleConfigured,
@@ -65799,6 +65793,7 @@ var config_get_default2 = defineController2(async ({ req, env: env2 }) => {
65799
65793
  localPassword,
65800
65794
  hosted,
65801
65795
  standardAgentsLogin,
65796
+ platformLoginUrl: hosted ? platformLoginUrl(req, env2, "/") : void 0,
65802
65797
  platformEndpoint: hasPlatformApiKey(env2) ? platformEndpoint(env2) : configuredPlatformEndpoint
65803
65798
  };
65804
65799
  });
@@ -65806,6 +65801,12 @@ var config_get_default2 = defineController2(async ({ req, env: env2 }) => {
65806
65801
  // src/api/auth/login.post.ts
65807
65802
  var login_post_default = defineController2(async ({ req, env: env2 }) => {
65808
65803
  try {
65804
+ if (isPlatformHosted(env2)) {
65805
+ return Response.json(
65806
+ { error: "Hosted instances authenticate through the Standard Agents platform." },
65807
+ { status: 404 }
65808
+ );
65809
+ }
65809
65810
  const body = await req.json();
65810
65811
  const { username, password } = body;
65811
65812
  if (!password) {
@@ -65931,6 +65932,100 @@ var me_get_default = defineController2(async ({ req, env: env2 }) => {
65931
65932
  }
65932
65933
  });
65933
65934
 
65935
+ // src/utils/platform-signed-payload.ts
65936
+ var encoder = new TextEncoder();
65937
+ var decoder = new TextDecoder();
65938
+ function base64UrlToBytes(value) {
65939
+ const padded = value.replace(/-/g, "+").replace(/_/g, "/") + "=".repeat((4 - value.length % 4) % 4);
65940
+ const binary = atob(padded);
65941
+ const bytes = new Uint8Array(binary.length);
65942
+ for (let index = 0; index < binary.length; index += 1) {
65943
+ bytes[index] = binary.charCodeAt(index);
65944
+ }
65945
+ return bytes;
65946
+ }
65947
+ function decodeJson(value) {
65948
+ return JSON.parse(decoder.decode(base64UrlToBytes(value)));
65949
+ }
65950
+ function parsePublicJwk(value) {
65951
+ if (typeof value !== "string" || !value.trim()) return null;
65952
+ try {
65953
+ const parsed = JSON.parse(value);
65954
+ if (parsed.kty !== "EC" || parsed.crv !== "P-256" || !parsed.x || !parsed.y) {
65955
+ return null;
65956
+ }
65957
+ return parsed;
65958
+ } catch {
65959
+ return null;
65960
+ }
65961
+ }
65962
+ async function importPublicKey(jwk) {
65963
+ return crypto.subtle.importKey(
65964
+ "jwk",
65965
+ jwk,
65966
+ { name: "ECDSA", namedCurve: "P-256" },
65967
+ false,
65968
+ ["verify"]
65969
+ );
65970
+ }
65971
+ async function verifyPlatformSignedPayload(token, publicJwkValue, options) {
65972
+ const publicJwk = parsePublicJwk(publicJwkValue);
65973
+ if (!publicJwk) return null;
65974
+ const normalized = token.startsWith("sap_") ? token.slice(4) : token;
65975
+ const parts = normalized.split(".");
65976
+ if (parts.length !== 3) return null;
65977
+ const [headerB64, payloadB64, signatureB64] = parts;
65978
+ let header;
65979
+ let payload;
65980
+ try {
65981
+ header = decodeJson(headerB64);
65982
+ payload = decodeJson(payloadB64);
65983
+ } catch {
65984
+ return null;
65985
+ }
65986
+ if (header.alg !== "ES256" || payload.kind !== options.kind) return null;
65987
+ if (options.projectId && payload.project_id !== options.projectId) return null;
65988
+ if (typeof payload.exp !== "number" || payload.exp < Math.floor(Date.now() / 1e3)) {
65989
+ return null;
65990
+ }
65991
+ const key = await importPublicKey(publicJwk);
65992
+ const signed = encoder.encode(`${headerB64}.${payloadB64}`);
65993
+ const signature = base64UrlToBytes(signatureB64);
65994
+ const verified = await crypto.subtle.verify(
65995
+ { name: "ECDSA", hash: "SHA-256" },
65996
+ key,
65997
+ signature,
65998
+ signed
65999
+ );
66000
+ return verified ? payload : null;
66001
+ }
66002
+
66003
+ // src/api/auth/platform-replica.post.ts
66004
+ var platform_replica_post_default = defineController2(async ({ req, env: env2 }) => {
66005
+ const body = await req.json().catch(() => null);
66006
+ const token = typeof body?.snapshot === "string" ? body.snapshot : req.headers.get("Authorization")?.startsWith("Bearer ") ? req.headers.get("Authorization").slice("Bearer ".length) : null;
66007
+ if (!token) {
66008
+ return Response.json({ error: "Missing replica snapshot" }, { status: 400 });
66009
+ }
66010
+ const payload = await verifyPlatformSignedPayload(
66011
+ token,
66012
+ env2.STANDARD_AGENTS_AUTH_PUBLIC_KEY_JWK ?? env2.STANDARD_AGENTS_AUTH_PUBLIC_KEY,
66013
+ {
66014
+ kind: "instance_snapshot",
66015
+ projectId: typeof env2.STANDARD_AGENTS_PROJECT_ID === "string" ? env2.STANDARD_AGENTS_PROJECT_ID : void 0
66016
+ }
66017
+ );
66018
+ if (!payload || !Array.isArray(payload.users)) {
66019
+ return Response.json({ error: "Invalid replica snapshot" }, { status: 401 });
66020
+ }
66021
+ const agentBuilder = env2.AGENT_BUILDER.get(env2.AGENT_BUILDER.idFromName("singleton"));
66022
+ const result = await agentBuilder.applyPlatformReplicaSnapshot({
66023
+ users: payload.users,
66024
+ api_keys: payload.api_keys ?? []
66025
+ });
66026
+ return Response.json({ ok: true, ...result });
66027
+ });
66028
+
65934
66029
  // src/api/envs/_shared.ts
65935
66030
  function buildScopedEnvResponse(entries) {
65936
66031
  const variables = [...entries].sort((a, b) => a.name.localeCompare(b.name)).map((entry) => ({
@@ -66314,6 +66409,12 @@ var npm_token_status_get_default = defineController2(async ({ env: env2 }) => {
66314
66409
 
66315
66410
  // src/api/platform/[...path].ts
66316
66411
  var path_default = defineController2(async ({ req, params, env: env2, url }) => {
66412
+ if (isPlatformHosted(env2)) {
66413
+ return Response.json(
66414
+ { error: "Platform proxy is disabled on hosted instances" },
66415
+ { status: 410 }
66416
+ );
66417
+ }
66317
66418
  const endpoints = resolvePlatformEndpointCandidates(req, env2);
66318
66419
  const apiKey = env2.PLATFORM_API_KEY;
66319
66420
  if (endpoints.length === 0 || !apiKey) {
@@ -66353,7 +66454,7 @@ var path_default = defineController2(async ({ req, params, env: env2, url }) =>
66353
66454
  });
66354
66455
 
66355
66456
  // src/api/platform-auth/bootstrap.post.ts
66356
- function uniqueEndpoints2(preferred, candidates) {
66457
+ function uniqueEndpoints(preferred, candidates) {
66357
66458
  return Array.from(new Set([preferred, ...candidates].filter((value) => Boolean(value))));
66358
66459
  }
66359
66460
  function buildSessionCookieHeader(req, sessionCookie) {
@@ -66367,6 +66468,12 @@ function buildSessionCookieHeader(req, sessionCookie) {
66367
66468
  return `${sessionCookie}; ${attributes.join("; ")}`;
66368
66469
  }
66369
66470
  var bootstrap_post_default2 = defineController2(async ({ req, env: env2 }) => {
66471
+ if (isPlatformHosted(env2)) {
66472
+ return Response.json(
66473
+ { error: "Platform auth bridge is disabled on hosted instances" },
66474
+ { status: 410 }
66475
+ );
66476
+ }
66370
66477
  const requestCookie = req.headers.get("Cookie")?.trim() || "";
66371
66478
  const configuredEndpoints = resolvePlatformEndpointCandidates(req, env2);
66372
66479
  let cookie = requestCookie;
@@ -66376,7 +66483,7 @@ var bootstrap_post_default2 = defineController2(async ({ req, env: env2 }) => {
66376
66483
  const bootstrap = findLocalBootstrapSession(void 0, env2)?.session;
66377
66484
  if (bootstrap?.session_cookie) {
66378
66485
  cookie = bootstrap.session_cookie;
66379
- endpoints = uniqueEndpoints2(bootstrap.endpoint, configuredEndpoints);
66486
+ endpoints = uniqueEndpoints(bootstrap.endpoint, configuredEndpoints);
66380
66487
  bootstrappedFromProject = true;
66381
66488
  } else {
66382
66489
  const localSession = await createPlatformLocalSession(env2);
@@ -66437,6 +66544,12 @@ var bootstrap_post_default2 = defineController2(async ({ req, env: env2 }) => {
66437
66544
 
66438
66545
  // src/api/platform-auth/login.post.ts
66439
66546
  var login_post_default2 = defineController2(async ({ req, env: env2 }) => {
66547
+ if (isPlatformHosted(env2)) {
66548
+ return Response.json(
66549
+ { error: "Platform auth bridge is disabled on hosted instances" },
66550
+ { status: 410 }
66551
+ );
66552
+ }
66440
66553
  const endpoints = resolvePlatformEndpointCandidates(req, env2);
66441
66554
  if (endpoints.length === 0) {
66442
66555
  const localSession = await createPlatformLocalSession(env2);
@@ -66489,6 +66602,9 @@ var login_post_default2 = defineController2(async ({ req, env: env2 }) => {
66489
66602
 
66490
66603
  // src/api/platform-auth/logout.post.ts
66491
66604
  var logout_post_default2 = defineController2(async ({ req, env: env2 }) => {
66605
+ if (isPlatformHosted(env2)) {
66606
+ return Response.json({ success: true });
66607
+ }
66492
66608
  const endpoints = resolvePlatformEndpointCandidates(req, env2);
66493
66609
  if (endpoints.length === 0) {
66494
66610
  return Response.json({ success: true });
@@ -66526,7 +66642,7 @@ var logout_post_default2 = defineController2(async ({ req, env: env2 }) => {
66526
66642
  });
66527
66643
 
66528
66644
  // src/api/platform-auth/me.get.ts
66529
- function uniqueEndpoints3(preferred, candidates) {
66645
+ function uniqueEndpoints2(preferred, candidates) {
66530
66646
  return Array.from(new Set([preferred, ...candidates].filter((value) => Boolean(value))));
66531
66647
  }
66532
66648
  function buildSessionCookieHeader2(req, sessionCookie) {
@@ -66540,6 +66656,12 @@ function buildSessionCookieHeader2(req, sessionCookie) {
66540
66656
  return `${sessionCookie}; ${attributes.join("; ")}`;
66541
66657
  }
66542
66658
  var me_get_default2 = defineController2(async ({ req, env: env2 }) => {
66659
+ if (isPlatformHosted(env2)) {
66660
+ return Response.json(
66661
+ { error: "Platform auth bridge is disabled on hosted instances" },
66662
+ { status: 410 }
66663
+ );
66664
+ }
66543
66665
  const requestCookie = req.headers.get("Cookie")?.trim() || "";
66544
66666
  const configuredEndpoints = resolvePlatformEndpointCandidates(req, env2);
66545
66667
  let cookie = requestCookie;
@@ -66549,7 +66671,7 @@ var me_get_default2 = defineController2(async ({ req, env: env2 }) => {
66549
66671
  const bootstrap = findLocalBootstrapSession(void 0, env2)?.session;
66550
66672
  if (bootstrap?.session_cookie) {
66551
66673
  cookie = bootstrap.session_cookie;
66552
- endpoints = uniqueEndpoints3(bootstrap.endpoint, configuredEndpoints);
66674
+ endpoints = uniqueEndpoints2(bootstrap.endpoint, configuredEndpoints);
66553
66675
  bootstrappedFromProject = true;
66554
66676
  } else {
66555
66677
  const identity = await getPlatformIdentity(env2);
@@ -66665,6 +66787,12 @@ async function proxyPlatformSessionRequest({
66665
66787
 
66666
66788
  // src/api/platform-session/[...path].ts
66667
66789
  var path_default2 = defineController2(async ({ req, params, env: env2, url }) => {
66790
+ if (isPlatformHosted(env2)) {
66791
+ return Response.json(
66792
+ { error: "Platform session proxy is disabled on hosted instances" },
66793
+ { status: 410 }
66794
+ );
66795
+ }
66668
66796
  if (!req.headers.get("Cookie") && hasPlatformApiKey(env2)) {
66669
66797
  return proxyPlatformSessionRequest({ req, params, env: env2 });
66670
66798
  }
@@ -68817,116 +68945,71 @@ var name_get_default7 = defineController2(async ({ params, url, prompts, agents,
68817
68945
 
68818
68946
  // src/api/auth/sa/callback.get.ts
68819
68947
  var SESSION_TTL_SECONDS2 = 30 * 24 * 60 * 60;
68820
- function readNamedCookie(req, name15) {
68821
- const header = req.headers.get("Cookie");
68822
- if (!header) return null;
68823
- for (const part of header.split(";")) {
68824
- const eq = part.indexOf("=");
68825
- if (eq === -1) continue;
68826
- if (part.slice(0, eq).trim() === name15) return decodeURIComponent(part.slice(eq + 1).trim()) || null;
68827
- }
68828
- return null;
68948
+ function safeReturnTo(value) {
68949
+ if (!value || !value.startsWith("/") || value.startsWith("//")) return "/";
68950
+ return value;
68829
68951
  }
68830
68952
  function failRedirect(req, reason) {
68831
68953
  const origin = new URL(req.url).origin;
68832
- const headers = new Headers({ Location: `${origin}/login?sa_error=${encodeURIComponent(reason)}` });
68833
- headers.append("Set-Cookie", "sa_oauth=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0");
68834
- return new Response(null, { status: 302, headers });
68954
+ return new Response(null, {
68955
+ status: 302,
68956
+ headers: { Location: `${origin}/login?sa_error=${encodeURIComponent(reason)}` }
68957
+ });
68835
68958
  }
68836
68959
  var callback_get_default = defineController2(async ({ req, env: env2 }) => {
68960
+ if (!isPlatformHosted(env2)) {
68961
+ return failRedirect(req, "not_hosted");
68962
+ }
68837
68963
  const url = new URL(req.url);
68838
- const code = url.searchParams.get("code");
68839
- const state = url.searchParams.get("state");
68840
- const stash = readNamedCookie(req, "sa_oauth");
68841
- if (!code || !state || !stash) {
68964
+ const handoff = url.searchParams.get("handoff") || url.searchParams.get("token");
68965
+ if (!handoff) {
68842
68966
  return failRedirect(req, "invalid_response");
68843
68967
  }
68844
- const sep = stash.indexOf(":");
68845
- const verifier = sep === -1 ? "" : stash.slice(0, sep);
68846
- const expectedState = sep === -1 ? "" : stash.slice(sep + 1);
68847
- if (!verifier || expectedState !== state) {
68848
- return failRedirect(req, "state_mismatch");
68849
- }
68850
- const clientId = typeof env2.STANDARD_AGENTS_OAUTH_CLIENT_ID === "string" ? env2.STANDARD_AGENTS_OAUTH_CLIENT_ID.trim() : "";
68851
- if (!clientId) {
68852
- return failRedirect(req, "not_configured");
68853
- }
68854
- const endpoint = platformEndpoint(env2);
68855
- const redirectUri = `${url.origin}/api/auth/sa/callback`;
68856
- let platformUserId;
68857
- try {
68858
- const tokenRes = await fetch(`${endpoint}/oauth/token`, {
68859
- method: "POST",
68860
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
68861
- body: new URLSearchParams({
68862
- grant_type: "authorization_code",
68863
- code,
68864
- client_id: clientId,
68865
- redirect_uri: redirectUri,
68866
- code_verifier: verifier
68867
- }).toString()
68868
- });
68869
- if (!tokenRes.ok) return failRedirect(req, "token_exchange_failed");
68870
- const tokenBody = await tokenRes.json().catch(() => ({}));
68871
- if (!tokenBody.access_token) return failRedirect(req, "token_exchange_failed");
68872
- const userRes = await fetch(`${endpoint}/oauth/userinfo`, {
68873
- headers: { Authorization: `Bearer ${tokenBody.access_token}` }
68874
- });
68875
- if (!userRes.ok) return failRedirect(req, "userinfo_failed");
68876
- const userinfo = await userRes.json().catch(() => ({}));
68877
- if (!userinfo.sub) return failRedirect(req, "userinfo_failed");
68878
- platformUserId = userinfo.sub;
68879
- } catch {
68880
- return failRedirect(req, "platform_unreachable");
68881
- }
68882
- const session = await mintLocalSessionForPlatformUser(env2, platformUserId);
68883
- const headers = new Headers({ Location: `${url.origin}/` });
68884
- headers.append("Set-Cookie", buildSessionCookie(req, session.token, SESSION_TTL_SECONDS2));
68885
- headers.append("Set-Cookie", "sa_oauth=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0");
68886
- return new Response(null, { status: 302, headers });
68968
+ const configuredProjectId = typeof env2.STANDARD_AGENTS_PROJECT_ID === "string" ? env2.STANDARD_AGENTS_PROJECT_ID : void 0;
68969
+ const payload = await verifyPlatformSignedPayload(
68970
+ handoff,
68971
+ env2.STANDARD_AGENTS_AUTH_PUBLIC_KEY_JWK ?? env2.STANDARD_AGENTS_AUTH_PUBLIC_KEY,
68972
+ {
68973
+ kind: "instance_handoff",
68974
+ projectId: configuredProjectId
68975
+ }
68976
+ );
68977
+ if (!payload || !payload.platform_user_id || !payload.role) {
68978
+ return failRedirect(req, "forbidden");
68979
+ }
68980
+ if (!configuredProjectId && payload.project_id !== hostedInstanceRedirectId(req, env2)) {
68981
+ return failRedirect(req, "forbidden");
68982
+ }
68983
+ const session = await mintLocalSessionForPlatformUser(env2, {
68984
+ platform_user_id: payload.platform_user_id,
68985
+ username: payload.username ?? null,
68986
+ display_name: payload.display_name ?? null,
68987
+ email: payload.email ?? null,
68988
+ avatar_url: payload.avatar_url ?? null,
68989
+ role: payload.role
68990
+ });
68991
+ const returnTo = safeReturnTo(url.searchParams.get("return_to"));
68992
+ return new Response(null, {
68993
+ status: 302,
68994
+ headers: {
68995
+ Location: `${url.origin}${returnTo}`,
68996
+ "Set-Cookie": buildSessionCookie(req, session.token, SESSION_TTL_SECONDS2)
68997
+ }
68998
+ });
68887
68999
  });
68888
69000
 
68889
69001
  // src/api/auth/sa/start.get.ts
68890
- function randomToken(bytesLength = 32) {
68891
- const bytes = new Uint8Array(bytesLength);
68892
- crypto.getRandomValues(bytes);
68893
- return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
68894
- }
68895
- function base64Url(bytes) {
68896
- let binary = "";
68897
- for (const byte of new Uint8Array(bytes)) binary += String.fromCharCode(byte);
68898
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
68899
- }
68900
- async function pkceChallenge(verifier) {
68901
- const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
68902
- return base64Url(digest);
68903
- }
68904
69002
  var start_get_default = defineController2(async ({ req, env: env2 }) => {
68905
- const clientId = typeof env2.STANDARD_AGENTS_OAUTH_CLIENT_ID === "string" ? env2.STANDARD_AGENTS_OAUTH_CLIENT_ID.trim() : "";
68906
- if (!clientId) {
68907
- return Response.json({ error: "Standard Agents login is not configured for this instance." }, { status: 400 });
69003
+ if (!isPlatformHosted(env2)) {
69004
+ return Response.json({ error: "Standard Agents hosted login is only available on deployed instances." }, { status: 404 });
68908
69005
  }
68909
- const verifier = randomToken(32);
68910
- const challenge = await pkceChallenge(verifier);
68911
- const state = randomToken(16);
68912
- const reqUrl = new URL(req.url);
68913
- const redirectUri = `${reqUrl.origin}/api/auth/sa/callback`;
68914
- const authorize = new URL(`${platformEndpoint(env2)}/oauth/authorize`);
68915
- authorize.searchParams.set("client_id", clientId);
68916
- authorize.searchParams.set("redirect_uri", redirectUri);
68917
- authorize.searchParams.set("code_challenge", challenge);
68918
- authorize.searchParams.set("code_challenge_method", "S256");
68919
- authorize.searchParams.set("state", state);
68920
- authorize.searchParams.set("scope", "openid profile email");
68921
- const attrs = ["Path=/", "HttpOnly", "SameSite=Lax", "Max-Age=600"];
68922
- try {
68923
- if (reqUrl.protocol === "https:") attrs.push("Secure");
68924
- } catch {
68925
- }
68926
- const oauthCookie = `sa_oauth=${encodeURIComponent(`${verifier}:${state}`)}; ${attrs.join("; ")}`;
69006
+ const url = new URL(req.url);
69007
+ const returnTo = url.searchParams.get("return_to") || "/";
68927
69008
  return new Response(null, {
68928
69009
  status: 302,
68929
- headers: { Location: authorize.toString(), "Set-Cookie": oauthCookie }
69010
+ headers: {
69011
+ Location: platformLoginUrl(req, env2, returnTo)
69012
+ }
68930
69013
  });
68931
69014
  });
68932
69015
 
@@ -70027,6 +70110,7 @@ var routeHandlers = {
70027
70110
  "POST:/auth/login": login_post_default,
70028
70111
  "POST:/auth/logout": logout_post_default,
70029
70112
  "GET:/auth/me": me_get_default,
70113
+ "POST:/auth/platform-replica": platform_replica_post_default,
70030
70114
  "GET:/envs/instance": instance_get_default,
70031
70115
  "PATCH:/envs/instance": instance_patch_default,
70032
70116
  "POST:/models/available": available_post_default,