@standardagents/builder 0.36.2 → 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.
- package/dist/built-in-routes.js +167 -131
- package/dist/built-in-routes.js.map +1 -1
- package/dist/client/{ApiKeysView-CxelZw61.js → ApiKeysView-CTfDKe47.js} +1 -1
- package/dist/client/{CenteredContentView-CeQNRQH8.js → CenteredContentView-BrVntknT.js} +1 -1
- package/dist/client/{CompositionView-YO0nHsYV.js → CompositionView-BT-1sFij.js} +1 -1
- 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
- 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
- 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
- package/dist/client/{JsonViewer-71rdOpyq.js → JsonViewer-DY4s92Td.js} +1 -1
- package/dist/client/{LoginView-CkDpPh8U.js → LoginView-DHYLpkb0.js} +1 -1
- package/dist/client/{MarketplaceView-UYrMBLon.js → MarketplaceView-Bcil0ES3.js} +1 -1
- 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
- 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
- package/dist/client/{ModelsView-DKYzp2fJ.js → ModelsView-_RY4gQ79.js} +1 -1
- package/dist/client/{PromptEditView-BlYHZ0ao.js → PromptEditView-D8kyGi30.js} +1 -1
- package/dist/client/{PromptModal-B1neRzSc.js → PromptModal-DSPIuleV.js} +1 -1
- package/dist/client/{PromptsView-C0Ez74j0.js → PromptsView-DPvBDPJf.js} +1 -1
- package/dist/client/{ProvidersView-CFc4K0IC.js → ProvidersView-PaPnME7I.js} +1 -1
- 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
- package/dist/client/{ThreadsView-B1hFXL-4.js → ThreadsView-BW4SYvFN.js} +1 -1
- package/dist/client/{ToolsView-B3KqeOZD.js → ToolsView-xsIVTHh0.js} +1 -1
- package/dist/client/{UsersView-CF1tomjI.js → UsersView-CSXdBGA-.js} +1 -1
- package/dist/client/{VariablesView-CP0TDspK.js → VariablesView-Bl5S2ZDn.js} +1 -1
- package/dist/client/assets/{ThreadInspectorPane-2QOWOtet.css → ThreadInspectorPane-CnbmdCdH.css} +1 -1
- package/dist/client/{index-BTs3PMFs.js → index-Df4DTwgs.js} +2 -2
- package/dist/client/index.html +1 -1
- package/dist/{index-DUIfQjBW.d.ts → index-yV9JL4r3.d.ts} +17 -1
- package/dist/index.d.ts +60 -2
- package/dist/index.js +10015 -9557
- package/dist/index.js.map +1 -1
- package/dist/plugin.js +3 -0
- package/dist/plugin.js.map +1 -1
- package/dist/runtime.d.ts +68 -3
- package/dist/runtime.js +10013 -9558
- package/dist/runtime.js.map +1 -1
- package/dist/test.d.ts +1 -1
- package/package.json +5 -5
package/dist/built-in-routes.js
CHANGED
|
@@ -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
|
-
|
|
8424
|
-
|
|
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
|
-
|
|
8800
|
-
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
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.
|
|
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,
|
|
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,
|