@standardagents/builder 0.36.3 → 0.37.0

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 (37) hide show
  1. package/dist/built-in-routes.js +167 -131
  2. package/dist/built-in-routes.js.map +1 -1
  3. package/dist/client/{ApiKeysView-CxelZw61.js → ApiKeysView-CTfDKe47.js} +1 -1
  4. package/dist/client/{CenteredContentView-CeQNRQH8.js → CenteredContentView-BrVntknT.js} +1 -1
  5. package/dist/client/{CompositionView-YO0nHsYV.js → CompositionView-BT-1sFij.js} +1 -1
  6. package/dist/client/{ConfirmDialog.vue_vue_type_script_setup_true_lang-_Y_F2vcO.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-yyjbXnqu.js} +1 -1
  7. package/dist/client/{CopyButton.vue_vue_type_script_setup_true_lang-CtC06f6H.js → CopyButton.vue_vue_type_script_setup_true_lang-BWgZbcol.js} +1 -1
  8. package/dist/client/{DataTable.vue_vue_type_script_setup_true_lang-CqaWkS63.js → DataTable.vue_vue_type_script_setup_true_lang-DP_WTiEu.js} +1 -1
  9. package/dist/client/{JsonViewer-71rdOpyq.js → JsonViewer-DY4s92Td.js} +1 -1
  10. package/dist/client/{LoginView-CkDpPh8U.js → LoginView-DHYLpkb0.js} +1 -1
  11. package/dist/client/{MarketplaceView-UYrMBLon.js → MarketplaceView-Bcil0ES3.js} +1 -1
  12. package/dist/client/{Modal.vue_vue_type_script_setup_true_lang-B1HPGo8o.js → Modal.vue_vue_type_script_setup_true_lang-BJgJZ56X.js} +1 -1
  13. package/dist/client/{ModelModal.vue_vue_type_script_setup_true_lang-DejoTM9W.js → ModelModal.vue_vue_type_script_setup_true_lang-BXTP0K4Z.js} +1 -1
  14. package/dist/client/{ModelsView-DKYzp2fJ.js → ModelsView-_RY4gQ79.js} +1 -1
  15. package/dist/client/{PromptEditView-BlYHZ0ao.js → PromptEditView-D8kyGi30.js} +1 -1
  16. package/dist/client/{PromptModal-B1neRzSc.js → PromptModal-DSPIuleV.js} +1 -1
  17. package/dist/client/{PromptsView-C0Ez74j0.js → PromptsView-DPvBDPJf.js} +1 -1
  18. package/dist/client/{ProvidersView-CFc4K0IC.js → ProvidersView-PaPnME7I.js} +1 -1
  19. package/dist/client/{ThreadInspectorPane.vue_vue_type_script_setup_true_lang-CXbSQo2-.js → ThreadInspectorPane.vue_vue_type_script_setup_true_lang-BAUlrnb6.js} +14 -14
  20. package/dist/client/{ThreadsView-B1hFXL-4.js → ThreadsView-BW4SYvFN.js} +1 -1
  21. package/dist/client/{ToolsView-B3KqeOZD.js → ToolsView-xsIVTHh0.js} +1 -1
  22. package/dist/client/{UsersView-CF1tomjI.js → UsersView-CSXdBGA-.js} +1 -1
  23. package/dist/client/{VariablesView-CP0TDspK.js → VariablesView-Bl5S2ZDn.js} +1 -1
  24. package/dist/client/assets/{ThreadInspectorPane-2QOWOtet.css → ThreadInspectorPane-CnbmdCdH.css} +1 -1
  25. package/dist/client/{index-BTs3PMFs.js → index-Df4DTwgs.js} +2 -2
  26. package/dist/client/index.html +1 -1
  27. package/dist/{index-DUIfQjBW.d.ts → index-yV9JL4r3.d.ts} +17 -1
  28. package/dist/index.d.ts +60 -2
  29. package/dist/index.js +10015 -9557
  30. package/dist/index.js.map +1 -1
  31. package/dist/plugin.js +3 -0
  32. package/dist/plugin.js.map +1 -1
  33. package/dist/runtime.d.ts +68 -3
  34. package/dist/runtime.js +10013 -9558
  35. package/dist/runtime.js.map +1 -1
  36. package/dist/test.d.ts +1 -1
  37. package/package.json +5 -5
@@ -6522,22 +6522,8 @@ var init_context = __esm({
6522
6522
  var FlowEngine_exports = {};
6523
6523
  __export(FlowEngine_exports, {
6524
6524
  FlowEngine: () => FlowEngine,
6525
- HookBlockedExecutionError: () => HookBlockedExecutionError,
6526
- stepBudgetMessage: () => stepBudgetMessage
6525
+ HookBlockedExecutionError: () => HookBlockedExecutionError
6527
6526
  });
6528
- function stepBudgetMessage(stepsRemaining) {
6529
- if (stepsRemaining > 20) return null;
6530
- if (stepsRemaining === 0) {
6531
- return "[STEP BUDGET] \u26A0\uFE0F CRITICAL: You must complete your task NOW or an error will be thrown. This is your final step.";
6532
- }
6533
- if (stepsRemaining === 1) {
6534
- return "[STEP BUDGET] \u26A0\uFE0F CRITICAL: Only 1 step available after this before an error will be thrown. Reach completion immediately.";
6535
- }
6536
- if (stepsRemaining <= 3) {
6537
- return `[STEP BUDGET] \u26A0\uFE0F WARNING: Only ${stepsRemaining} steps available before an error will be thrown. Reach completion as soon as possible.`;
6538
- }
6539
- return `[STEP BUDGET] ${stepsRemaining} steps available before an error will be thrown. Work efficiently toward completion.`;
6540
- }
6541
6527
  var IMMEDIATE_BOOTSTRAP_TOOL_NAME, HookBlockedExecutionError, FlowEngine;
6542
6528
  var init_FlowEngine = __esm({
6543
6529
  "src/agents/FlowEngine.ts"() {
@@ -6651,7 +6637,8 @@ var init_FlowEngine = __esm({
6651
6637
  try {
6652
6638
  const detail = error instanceof Error ? error.message : String(error);
6653
6639
  await state.thread.instance.settleTerminalFailure?.(
6654
- `The agent run failed unexpectedly: ${detail}`
6640
+ `The agent run failed unexpectedly: ${detail}`,
6641
+ state.threadId
6655
6642
  );
6656
6643
  } catch (settleError) {
6657
6644
  console.error("[FlowEngine] Failed to settle terminal failure (non-fatal):", settleError);
@@ -8160,6 +8147,17 @@ This usually points to something I can't fix from here \u2014 for example the wo
8160
8147
  if (hidden.size === 0) return registry;
8161
8148
  return registry.filter((entry) => !hidden.has(entry.name));
8162
8149
  }
8150
+ /**
8151
+ * True when the prompt declares any resumable subagent config — the exact
8152
+ * condition under which the runtime injects `subagent_create` and the
8153
+ * `subagents` query tool, i.e. the pull path for child state exists.
8154
+ */
8155
+ static hasResumableSubagentConfigs(state) {
8156
+ const configs = state.prompt?._tools ?? [];
8157
+ return configs.some(
8158
+ (t) => typeof t === "object" && t !== null && Boolean(t.resumable)
8159
+ );
8160
+ }
8163
8161
  /** Public snapshot for the `subagents` built-in tool (ToolExecutor). */
8164
8162
  static async listModelVisibleSubagents(state) {
8165
8163
  return _FlowEngine.filterModelVisibleSubagents(
@@ -8420,43 +8418,11 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
8420
8418
  }
8421
8419
  messages.push(messageToAdd);
8422
8420
  }
8423
- const maxSteps = state.currentSide === "a" ? state.agentConfig.side_a_max_steps : state.agentConfig.side_b_max_steps;
8424
- if (typeof maxSteps === "number" && !isNaN(maxSteps)) {
8425
- const currentSideStepCount = state.currentSide === "a" ? state.sideAStepCount : state.sideBStepCount;
8426
- const stepsRemaining = maxSteps - currentSideStepCount;
8427
- const budgetMessage = stepBudgetMessage(stepsRemaining);
8428
- if (budgetMessage) {
8429
- messages.push({
8430
- role: "system",
8431
- content: budgetMessage
8432
- });
8433
- }
8434
- }
8435
- const subagentRegistry = _FlowEngine.filterModelVisibleSubagents(
8421
+ state.currentSide === "a" ? state.agentConfig.side_a_max_steps : state.agentConfig.side_b_max_steps;
8422
+ _FlowEngine.filterModelVisibleSubagents(
8436
8423
  await this.getSubagentRegistry(state),
8437
8424
  state.prompt?._tools
8438
8425
  );
8439
- const suppressRegistryMessage = Array.isArray(state.prompt?.hooks) ? state.prompt.hooks.includes("append_static_session_env") : false;
8440
- if (subagentRegistry.length > 0 && !suppressRegistryMessage) {
8441
- const fallbackNameMap = await this.resolveRegistryThreadNameMap(state, subagentRegistry);
8442
- const lines = subagentRegistry.map((entry) => {
8443
- const threadName = this.getRegistryThreadName(entry) ?? fallbackNameMap.get(entry.reference) ?? null;
8444
- const displayName = threadName ? `${entry.name} (${threadName})` : entry.name;
8445
- const initialArguments = this.getRegistryInitialArguments(entry);
8446
- const argumentsLine = initialArguments ? `
8447
- Initial arguments: ${this.formatInitialArgumentsForPrompt(initialArguments)}` : "";
8448
- return `- Reference: ${entry.reference}
8449
- Name: ${displayName}
8450
- Description: ${entry.description}
8451
- Status: ${entry.status}${argumentsLine}`;
8452
- });
8453
- messages.push({
8454
- role: "system",
8455
- content: `Active subagent instances:
8456
-
8457
- ${lines.join("\n\n")}`
8458
- });
8459
- }
8460
8426
  const tools = await this.getToolsForPrompt(state, state.prompt);
8461
8427
  let finalToolChoice;
8462
8428
  if (toolChoice === "function" && tools.length === 1) {
@@ -8796,16 +8762,16 @@ ${lines.join("\n\n")}`
8796
8762
  }
8797
8763
  if (resumablePromptSubagents.length > 0 && !tools.some((tool3) => tool3.function.name === "subagent_create")) {
8798
8764
  tools.push(this.buildSubagentCreateTool(resumablePromptSubagents));
8799
- if (!tools.some((tool3) => tool3.function.name === "subagents")) {
8800
- tools.push({
8801
- type: "function",
8802
- function: {
8803
- name: "subagents",
8804
- description: "List your active subagent instances: reference id, name, status, and working-status text. Use when you need to check on children you created; completions also arrive as messages.",
8805
- parameters: { type: "object", properties: {} }
8806
- }
8807
- });
8808
- }
8765
+ }
8766
+ if ((resumablePromptSubagents.length > 0 || childrenRegistry.length > 0) && !tools.some((tool3) => tool3.function.name === "subagents")) {
8767
+ tools.push({
8768
+ type: "function",
8769
+ function: {
8770
+ name: "subagents",
8771
+ description: "List your active subagent instances: reference id, name, status, and working-status text. Call this BEFORE subagent_create to see whether an existing instance already covers the work, and whenever you need to check on children you created; completions also arrive as messages.",
8772
+ parameters: { type: "object", properties: {} }
8773
+ }
8774
+ });
8809
8775
  }
8810
8776
  const hasActiveResumable = childrenRegistry.some(
8811
8777
  (entry) => entry.status !== "terminated"
@@ -9109,6 +9075,7 @@ ${lines.join("\n\n")}`
9109
9075
  "Available resumable subagents:",
9110
9076
  ...descriptionLines,
9111
9077
  "Provide any required invocation arguments via `arguments`; they persist for the life of the subagent thread.",
9078
+ "Before creating a new instance, call `subagents` to check the status of instances you already have \u2014 an existing one may already cover the work, and instance caps count live children.",
9112
9079
  "Use subagent_message for follow-up communication with resumable instances."
9113
9080
  ].join("\n"),
9114
9081
  parameters: {
@@ -13337,6 +13304,25 @@ var init_ThreadStateImpl = __esm({
13337
13304
  const mustParkForApproval = request.requestPermission != null && await this.forwardedCallNeedsApproval(request);
13338
13305
  if (mustParkForApproval && canPark && toolCallId && typeof instance.hasBridge === "function" && await instance.hasBridge()) {
13339
13306
  await instance.dispatchClientTool(request, toolCallId, side);
13307
+ const getDelivered = instance.getDeliveredClientToolResult;
13308
+ if (typeof getDelivered === "function") {
13309
+ const graceDeadline = Date.now() + 4e3;
13310
+ while (Date.now() < graceDeadline) {
13311
+ await new Promise((r) => setTimeout(r, 150));
13312
+ try {
13313
+ const delivered = await getDelivered.call(instance, toolCallId);
13314
+ if (delivered) {
13315
+ return {
13316
+ ok: delivered.toolStatus !== "error",
13317
+ result: delivered.content,
13318
+ data: { toolCallId }
13319
+ };
13320
+ }
13321
+ } catch {
13322
+ break;
13323
+ }
13324
+ }
13325
+ }
13340
13326
  this._executionState.stop();
13341
13327
  return {
13342
13328
  ok: true,
@@ -67831,7 +67817,7 @@ var config_get_default = defineController2(async ({ config, env: env2, req }) =>
67831
67817
  });
67832
67818
 
67833
67819
  // src/version.ts
67834
- var BUILDER_VERSION = "0.36.3".length > 0 ? "0.36.3" : "dev";
67820
+ var BUILDER_VERSION = "0.37.0".length > 0 ? "0.37.0" : "dev";
67835
67821
 
67836
67822
  // src/api/diagnostics.get.ts
67837
67823
  init_LLMRequest();
@@ -68985,10 +68971,22 @@ var migration16 = {
68985
68971
  }
68986
68972
  };
68987
68973
 
68974
+ // src/durable-objects/agentbuilder-migrations/0017_add_thread_message_recency.ts
68975
+ var migration17 = {
68976
+ version: 17,
68977
+ async up(sql) {
68978
+ sql.exec(`ALTER TABLE threads ADD COLUMN last_message_at INTEGER`);
68979
+ sql.exec(`UPDATE threads SET last_message_at = created_at`);
68980
+ sql.exec(`
68981
+ INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '17')
68982
+ `);
68983
+ }
68984
+ };
68985
+
68988
68986
  // src/durable-objects/agentbuilder-migrations/index.ts
68989
- var migrations = [migration, migration2, migration3, migration4, migration5, migration6, migration7, migration8, migration9, migration10, migration11, migration12, migration13, migration14, migration15, migration16];
68987
+ var migrations = [migration, migration2, migration3, migration4, migration5, migration6, migration7, migration8, migration9, migration10, migration11, migration12, migration13, migration14, migration15, migration16, migration17];
68990
68988
  migrations.reduce(
68991
- (max, migration17) => Math.max(max, migration17.version),
68989
+ (max, migration18) => Math.max(max, migration18.version),
68992
68990
  0
68993
68991
  );
68994
68992
 
@@ -69110,6 +69108,7 @@ var threads_default = defineController2(async ({ req, env: env2 }) => {
69110
69108
  last_activity_at: thread.last_activity_at ?? thread.created_at,
69111
69109
  executing: thread.executing === true,
69112
69110
  last_message_preview: thread.last_message_preview ?? null,
69111
+ last_message_at: thread.last_message_at ?? null,
69113
69112
  agent: agentDetails
69114
69113
  };
69115
69114
  })
@@ -70438,6 +70437,110 @@ var bootstrap_post_default = defineController2(async ({ env: env2 }) => {
70438
70437
  }
70439
70438
  });
70440
70439
 
70440
+ // src/utils/platform-signed-payload.ts
70441
+ var encoder = new TextEncoder();
70442
+ var decoder = new TextDecoder();
70443
+ function base64UrlToBytes(value) {
70444
+ const padded = value.replace(/-/g, "+").replace(/_/g, "/") + "=".repeat((4 - value.length % 4) % 4);
70445
+ const binary = atob(padded);
70446
+ const bytes = new Uint8Array(binary.length);
70447
+ for (let index = 0; index < binary.length; index += 1) {
70448
+ bytes[index] = binary.charCodeAt(index);
70449
+ }
70450
+ return bytes;
70451
+ }
70452
+ function decodeJson(value) {
70453
+ return JSON.parse(decoder.decode(base64UrlToBytes(value)));
70454
+ }
70455
+ function parsePublicJwk(value) {
70456
+ if (typeof value !== "string" || !value.trim()) return null;
70457
+ try {
70458
+ const parsed = JSON.parse(value);
70459
+ if (parsed.kty !== "EC" || parsed.crv !== "P-256" || !parsed.x || !parsed.y) {
70460
+ return null;
70461
+ }
70462
+ return parsed;
70463
+ } catch {
70464
+ return null;
70465
+ }
70466
+ }
70467
+ async function importPublicKey(jwk) {
70468
+ return crypto.subtle.importKey(
70469
+ "jwk",
70470
+ jwk,
70471
+ { name: "ECDSA", namedCurve: "P-256" },
70472
+ false,
70473
+ ["verify"]
70474
+ );
70475
+ }
70476
+ async function verifyPlatformSignedPayload(token, publicJwkValue, options) {
70477
+ const publicJwk = parsePublicJwk(publicJwkValue);
70478
+ if (!publicJwk) return null;
70479
+ const normalized = token.startsWith("sap_") ? token.slice(4) : token;
70480
+ const parts = normalized.split(".");
70481
+ if (parts.length !== 3) return null;
70482
+ const [headerB64, payloadB64, signatureB64] = parts;
70483
+ let header;
70484
+ let payload;
70485
+ try {
70486
+ header = decodeJson(headerB64);
70487
+ payload = decodeJson(payloadB64);
70488
+ } catch {
70489
+ return null;
70490
+ }
70491
+ if (header.alg !== "ES256" || payload.kind !== options.kind) return null;
70492
+ if (options.projectId && payload.project_id !== options.projectId) return null;
70493
+ if (typeof payload.exp !== "number" || payload.exp < Math.floor(Date.now() / 1e3)) {
70494
+ return null;
70495
+ }
70496
+ const key = await importPublicKey(publicJwk);
70497
+ const signed = encoder.encode(`${headerB64}.${payloadB64}`);
70498
+ const signature = base64UrlToBytes(signatureB64);
70499
+ const verified = await crypto.subtle.verify(
70500
+ { name: "ECDSA", hash: "SHA-256" },
70501
+ key,
70502
+ signature,
70503
+ signed
70504
+ );
70505
+ return verified ? payload : null;
70506
+ }
70507
+
70508
+ // src/api/auth/brolly-control.post.ts
70509
+ var brolly_control_post_default = defineController2(async ({ req, env: env2 }) => {
70510
+ const authorization = req.headers.get("Authorization") ?? "";
70511
+ const token = authorization.startsWith("Brolly ") ? authorization.slice("Brolly ".length) : null;
70512
+ if (!token) return Response.json({ error: "Missing Brolly control token" }, { status: 400 });
70513
+ const projectId = typeof env2.STANDARD_AGENTS_PROJECT_ID === "string" ? env2.STANDARD_AGENTS_PROJECT_ID : void 0;
70514
+ const payload = await verifyPlatformSignedPayload(
70515
+ token,
70516
+ env2.BROLLY_CONTROL_PUBLIC_KEY_JWK,
70517
+ { kind: "brolly_runtime_control", projectId }
70518
+ );
70519
+ if (!payload) return Response.json({ error: "Invalid Brolly control token" }, { status: 401 });
70520
+ const configuredAccount = typeof env2.BROLLY_ACCOUNT_ID === "string" ? env2.BROLLY_ACCOUNT_ID : typeof env2.CLOUDFLARE_ACCOUNT_ID === "string" ? env2.CLOUDFLARE_ACCOUNT_ID : void 0;
70521
+ if (configuredAccount && payload.account_id !== configuredAccount) {
70522
+ return Response.json({ error: "Brolly account mismatch" }, { status: 403 });
70523
+ }
70524
+ if (payload.version !== 1 || !/^[0-9a-f]{64}$/i.test(payload.object_id) || !payload.action_id || !payload.reason) {
70525
+ return Response.json({ error: "Invalid Brolly control payload" }, { status: 400 });
70526
+ }
70527
+ const stub = env2.AGENT_BUILDER_THREAD.get(
70528
+ env2.AGENT_BUILDER_THREAD.idFromString(payload.object_id)
70529
+ );
70530
+ let status;
70531
+ if (payload.action === "quarantine") {
70532
+ if (typeof stub.emergencyQuarantine !== "function") return Response.json({ error: "Runtime quarantine is unsupported" }, { status: 501 });
70533
+ status = await stub.emergencyQuarantine({ actionId: payload.action_id, reason: payload.reason, source: "brolly", forensicHold: payload.forensic_hold, observed: payload.observed });
70534
+ } else if (payload.action === "resume") {
70535
+ if (typeof stub.emergencyResume !== "function") return Response.json({ error: "Runtime resume is unsupported" }, { status: 501 });
70536
+ status = await stub.emergencyResume({ actionId: payload.action_id, reason: payload.reason, releaseForensicHold: payload.release_forensic_hold });
70537
+ } else {
70538
+ if (typeof stub.getRuntimeSafetyStatus !== "function") return Response.json({ error: "Runtime status is unsupported" }, { status: 501 });
70539
+ status = await stub.getRuntimeSafetyStatus();
70540
+ }
70541
+ return Response.json({ ok: true, object_id: payload.object_id, action_id: payload.action_id, status });
70542
+ });
70543
+
70441
70544
  // src/api/auth/config.get.ts
70442
70545
  var config_get_default2 = defineController2(async ({ req, env: env2 }) => {
70443
70546
  const githubConfigured = !!(env2.GITHUB_CLIENT_ID && env2.GITHUB_CLIENT_SECRET);
@@ -70624,74 +70727,6 @@ var me_get_default = defineController2(async ({ req, env: env2 }) => {
70624
70727
  }
70625
70728
  });
70626
70729
 
70627
- // src/utils/platform-signed-payload.ts
70628
- var encoder = new TextEncoder();
70629
- var decoder = new TextDecoder();
70630
- function base64UrlToBytes(value) {
70631
- const padded = value.replace(/-/g, "+").replace(/_/g, "/") + "=".repeat((4 - value.length % 4) % 4);
70632
- const binary = atob(padded);
70633
- const bytes = new Uint8Array(binary.length);
70634
- for (let index = 0; index < binary.length; index += 1) {
70635
- bytes[index] = binary.charCodeAt(index);
70636
- }
70637
- return bytes;
70638
- }
70639
- function decodeJson(value) {
70640
- return JSON.parse(decoder.decode(base64UrlToBytes(value)));
70641
- }
70642
- function parsePublicJwk(value) {
70643
- if (typeof value !== "string" || !value.trim()) return null;
70644
- try {
70645
- const parsed = JSON.parse(value);
70646
- if (parsed.kty !== "EC" || parsed.crv !== "P-256" || !parsed.x || !parsed.y) {
70647
- return null;
70648
- }
70649
- return parsed;
70650
- } catch {
70651
- return null;
70652
- }
70653
- }
70654
- async function importPublicKey(jwk) {
70655
- return crypto.subtle.importKey(
70656
- "jwk",
70657
- jwk,
70658
- { name: "ECDSA", namedCurve: "P-256" },
70659
- false,
70660
- ["verify"]
70661
- );
70662
- }
70663
- async function verifyPlatformSignedPayload(token, publicJwkValue, options) {
70664
- const publicJwk = parsePublicJwk(publicJwkValue);
70665
- if (!publicJwk) return null;
70666
- const normalized = token.startsWith("sap_") ? token.slice(4) : token;
70667
- const parts = normalized.split(".");
70668
- if (parts.length !== 3) return null;
70669
- const [headerB64, payloadB64, signatureB64] = parts;
70670
- let header;
70671
- let payload;
70672
- try {
70673
- header = decodeJson(headerB64);
70674
- payload = decodeJson(payloadB64);
70675
- } catch {
70676
- return null;
70677
- }
70678
- if (header.alg !== "ES256" || payload.kind !== options.kind) return null;
70679
- if (options.projectId && payload.project_id !== options.projectId) return null;
70680
- if (typeof payload.exp !== "number" || payload.exp < Math.floor(Date.now() / 1e3)) {
70681
- return null;
70682
- }
70683
- const key = await importPublicKey(publicJwk);
70684
- const signed = encoder.encode(`${headerB64}.${payloadB64}`);
70685
- const signature = base64UrlToBytes(signatureB64);
70686
- const verified = await crypto.subtle.verify(
70687
- { name: "ECDSA", hash: "SHA-256" },
70688
- key,
70689
- signature,
70690
- signed
70691
- );
70692
- return verified ? payload : null;
70693
- }
70694
-
70695
70730
  // src/api/auth/platform-cleanup.post.ts
70696
70731
  var platform_cleanup_post_default = defineController2(async ({ req, env: env2 }) => {
70697
70732
  const body = await req.json().catch(() => null);
@@ -75738,6 +75773,7 @@ var routeHandlers = {
75738
75773
  "DELETE:/users/:id": id_delete_default3,
75739
75774
  "PUT:/users/:id": id_put_default,
75740
75775
  "POST:/auth/bootstrap": bootstrap_post_default,
75776
+ "POST:/auth/brolly-control": brolly_control_post_default,
75741
75777
  "GET:/auth/config": config_get_default2,
75742
75778
  "POST:/auth/login": login_post_default,
75743
75779
  "GET:/auth/logout": logout_get_default,