@standardagents/builder 0.38.0 → 0.38.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/built-in-routes.js +1165 -366
- package/dist/built-in-routes.js.map +1 -1
- package/dist/client/{ApiKeysView-L85eJb6G.js → ApiKeysView-AH5i-H6j.js} +1 -1
- package/dist/client/CenteredContentView-DaBp0K-A.js +1 -0
- package/dist/client/{CompositionView-BGp0EJCk.js → CompositionView-yY1Q4M23.js} +1 -1
- package/dist/client/{ConfirmDialog.vue_vue_type_script_setup_true_lang-DgwqZrLV.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-Bwo5CJzF.js} +1 -1
- package/dist/client/{CopyButton.vue_vue_type_script_setup_true_lang-B8cGgU2J.js → CopyButton.vue_vue_type_script_setup_true_lang-D0WYwWyA.js} +1 -1
- package/dist/client/{DataTable.vue_vue_type_script_setup_true_lang-CRBXym9D.js → DataTable.vue_vue_type_script_setup_true_lang-1wwPn2aY.js} +1 -1
- package/dist/client/{JsonViewer-DkHnIfq3.js → JsonViewer-Bi8Zdmir.js} +1 -1
- package/dist/client/LoginView-BIKahEU6.js +1 -0
- package/dist/client/{MarketplaceView-DEnujUBs.js → MarketplaceView-DPDPVH68.js} +1 -1
- package/dist/client/{Modal.vue_vue_type_script_setup_true_lang-keKEwm3K.js → Modal.vue_vue_type_script_setup_true_lang-D1_rfOsy.js} +1 -1
- package/dist/client/{ModelModal.vue_vue_type_script_setup_true_lang-t1n0bbJe.js → ModelModal.vue_vue_type_script_setup_true_lang-DSLeOdxr.js} +1 -1
- package/dist/client/{ModelsView-BkCLr8sp.js → ModelsView-Q2WXu1Gw.js} +1 -1
- package/dist/client/{PromptEditView-BjCfsJQE.js → PromptEditView-BzA-3n1w.js} +1 -1
- package/dist/client/{PromptModal-nxu_LIv6.js → PromptModal-CJWh_cru.js} +1 -1
- package/dist/client/{PromptsView-1yXGCmEZ.js → PromptsView-BezNl-Et.js} +1 -1
- package/dist/client/{ProvidersView-DxF6gafk.js → ProvidersView-BuzSKxuT.js} +1 -1
- package/dist/client/ThreadInspectorPane.vue_vue_type_script_setup_true_lang-DOxNp_3C.js +22 -0
- package/dist/client/{ThreadsView-CBup_w8u.js → ThreadsView-DPCpZA4J.js} +1 -1
- package/dist/client/{ToolsView-B30TfXU9.js → ToolsView-DMjFMAhH.js} +1 -1
- package/dist/client/{UiCodeBlock.vue_vue_type_script_setup_true_lang-BdyzSxZZ.js → UiCodeBlock.vue_vue_type_script_setup_true_lang-7FgZmkfs.js} +1 -1
- package/dist/client/{UsersView-kE7Xr4f3.js → UsersView-B7jXLNQs.js} +1 -1
- package/dist/client/{VariablesView-yYuynG0M.js → VariablesView-CF7x0G8g.js} +1 -1
- package/dist/client/assets/{ThreadInspectorPane-BRGO_P0_.css → ThreadInspectorPane-CZMdV0Tb.css} +1 -1
- package/dist/client/assets/{index-B-69GGhJ.css → index-DAABRRAA.css} +1 -1
- package/dist/client/{check-YKi1o6p6.js → check-CD2lvcVi.js} +1 -1
- package/dist/client/{chevron-right-T0zzq_GX.js → chevron-right-bWZrmJ5a.js} +1 -1
- package/dist/client/{copy-C_gUGAj1.js → copy-B7nifl6a.js} +1 -1
- package/dist/client/{formkit-CE26dtFp.js → formkit-DJxUzqRQ.js} +1 -1
- package/dist/client/index-eGECJFYe.js +6 -0
- package/dist/client/index.html +6 -6
- package/dist/client/{package-B70IFSDB.js → package-Dyv7fTIQ.js} +1 -1
- package/dist/client/{plus-BN9IHYdt.js → plus-XkSslfF4.js} +1 -1
- package/dist/client/{syntax-D-ZcovVx.js → syntax-D68HCEYm.js} +1 -1
- package/dist/client/{timeAgo-G1ovbWPH.js → timeAgo-DRBdu9ed.js} +1 -1
- package/dist/client/{useActionFeedback-7pfPjKMi.js → useActionFeedback-FN4t6ezB.js} +1 -1
- package/dist/client/{vendor-TPZjEwCU.js → vendor-c_uwtQ-S.js} +13 -13
- package/dist/client/{vue-CZ-ORfS3.js → vue-BuvSxRmI.js} +1 -1
- package/dist/{index-BBu-Osn5.d.ts → index-CF-lgN47.d.ts} +74 -11
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1060 -303
- package/dist/index.js.map +1 -1
- package/dist/plugin.js +102 -68
- package/dist/plugin.js.map +1 -1
- package/dist/runtime.d.ts +68 -11
- package/dist/runtime.js +950 -225
- package/dist/runtime.js.map +1 -1
- package/dist/test.d.ts +1 -1
- package/package.json +7 -6
- package/dist/client/CenteredContentView-D9jkWoLc.js +0 -1
- package/dist/client/LoginView-BXD9Odc-.js +0 -1
- package/dist/client/ThreadInspectorPane.vue_vue_type_script_setup_true_lang-CjwWJ3uw.js +0 -22
- package/dist/client/index-AUGwDdSH.js +0 -6
package/dist/built-in-routes.js
CHANGED
|
@@ -49,6 +49,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
49
49
|
mod
|
|
50
50
|
));
|
|
51
51
|
|
|
52
|
+
// src/skills/scope.ts
|
|
53
|
+
var SHARED_SKILL_OWNER;
|
|
54
|
+
var init_scope = __esm({
|
|
55
|
+
"src/skills/scope.ts"() {
|
|
56
|
+
SHARED_SKILL_OWNER = "__instance_shared__";
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
52
60
|
// src/agents/client-forwarding.ts
|
|
53
61
|
function createRuntimeStreams(openClientStream) {
|
|
54
62
|
return {
|
|
@@ -3123,6 +3131,104 @@ var init_sessionTools = __esm({
|
|
|
3123
3131
|
}
|
|
3124
3132
|
});
|
|
3125
3133
|
|
|
3134
|
+
// src/utils/remoteAttachment.ts
|
|
3135
|
+
function parseAllowedHosts(value) {
|
|
3136
|
+
if (typeof value !== "string") {
|
|
3137
|
+
return /* @__PURE__ */ new Set();
|
|
3138
|
+
}
|
|
3139
|
+
return new Set(
|
|
3140
|
+
value.split(",").map((host) => host.trim().toLowerCase().replace(/\.$/, "")).filter(Boolean)
|
|
3141
|
+
);
|
|
3142
|
+
}
|
|
3143
|
+
function isForbiddenHostname(hostname) {
|
|
3144
|
+
const normalized = hostname.toLowerCase().replace(/\.$/, "");
|
|
3145
|
+
if (/^\d{1,3}(?:\.\d{1,3}){3}$/.test(normalized)) {
|
|
3146
|
+
return true;
|
|
3147
|
+
}
|
|
3148
|
+
if (normalized.startsWith("[") && normalized.endsWith("]")) {
|
|
3149
|
+
return true;
|
|
3150
|
+
}
|
|
3151
|
+
if (!normalized.includes(".")) {
|
|
3152
|
+
return true;
|
|
3153
|
+
}
|
|
3154
|
+
return FORBIDDEN_HOST_SUFFIXES.some(
|
|
3155
|
+
(suffix) => normalized === suffix.slice(1) || normalized.endsWith(suffix)
|
|
3156
|
+
);
|
|
3157
|
+
}
|
|
3158
|
+
function validateRemoteAttachmentUrl(value, allowedHostsValue) {
|
|
3159
|
+
let url;
|
|
3160
|
+
try {
|
|
3161
|
+
url = new URL(value);
|
|
3162
|
+
} catch {
|
|
3163
|
+
return null;
|
|
3164
|
+
}
|
|
3165
|
+
if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.port !== "" && url.port !== "443") {
|
|
3166
|
+
return null;
|
|
3167
|
+
}
|
|
3168
|
+
const hostname = url.hostname.toLowerCase().replace(/\.$/, "");
|
|
3169
|
+
if (isForbiddenHostname(hostname)) {
|
|
3170
|
+
return null;
|
|
3171
|
+
}
|
|
3172
|
+
const allowedHosts = parseAllowedHosts(allowedHostsValue);
|
|
3173
|
+
if (!allowedHosts.has(hostname)) {
|
|
3174
|
+
return null;
|
|
3175
|
+
}
|
|
3176
|
+
return url;
|
|
3177
|
+
}
|
|
3178
|
+
async function fetchRemoteAttachment(location, allowedHostsValue, fetchImpl = fetch) {
|
|
3179
|
+
let url = validateRemoteAttachmentUrl(location, allowedHostsValue);
|
|
3180
|
+
if (!url) {
|
|
3181
|
+
return null;
|
|
3182
|
+
}
|
|
3183
|
+
for (let redirectCount = 0; redirectCount <= MAX_REDIRECTS; redirectCount++) {
|
|
3184
|
+
let response;
|
|
3185
|
+
try {
|
|
3186
|
+
response = await fetchImpl(url.toString(), {
|
|
3187
|
+
redirect: "manual"
|
|
3188
|
+
});
|
|
3189
|
+
} catch {
|
|
3190
|
+
return null;
|
|
3191
|
+
}
|
|
3192
|
+
if (!REDIRECT_STATUSES.has(response.status)) {
|
|
3193
|
+
return response.ok ? response : null;
|
|
3194
|
+
}
|
|
3195
|
+
await response.body?.cancel().catch(() => void 0);
|
|
3196
|
+
if (redirectCount === MAX_REDIRECTS) {
|
|
3197
|
+
return null;
|
|
3198
|
+
}
|
|
3199
|
+
const redirectLocation = response.headers.get("Location");
|
|
3200
|
+
if (!redirectLocation) {
|
|
3201
|
+
return null;
|
|
3202
|
+
}
|
|
3203
|
+
let resolvedLocation;
|
|
3204
|
+
try {
|
|
3205
|
+
resolvedLocation = new URL(redirectLocation, url).toString();
|
|
3206
|
+
} catch {
|
|
3207
|
+
return null;
|
|
3208
|
+
}
|
|
3209
|
+
url = validateRemoteAttachmentUrl(resolvedLocation, allowedHostsValue);
|
|
3210
|
+
if (!url) {
|
|
3211
|
+
return null;
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
3214
|
+
return null;
|
|
3215
|
+
}
|
|
3216
|
+
var REDIRECT_STATUSES, MAX_REDIRECTS, FORBIDDEN_HOST_SUFFIXES;
|
|
3217
|
+
var init_remoteAttachment = __esm({
|
|
3218
|
+
"src/utils/remoteAttachment.ts"() {
|
|
3219
|
+
REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
3220
|
+
MAX_REDIRECTS = 3;
|
|
3221
|
+
FORBIDDEN_HOST_SUFFIXES = [
|
|
3222
|
+
".internal",
|
|
3223
|
+
".lan",
|
|
3224
|
+
".local",
|
|
3225
|
+
".localhost",
|
|
3226
|
+
".home",
|
|
3227
|
+
".test"
|
|
3228
|
+
];
|
|
3229
|
+
}
|
|
3230
|
+
});
|
|
3231
|
+
|
|
3126
3232
|
// src/durable-objects/files.ts
|
|
3127
3233
|
var files_exports = {};
|
|
3128
3234
|
__export(files_exports, {
|
|
@@ -3860,6 +3966,7 @@ var init_ToolExecutor = __esm({
|
|
|
3860
3966
|
init_types();
|
|
3861
3967
|
init_ThreadStateImpl();
|
|
3862
3968
|
init_sessionTools();
|
|
3969
|
+
init_remoteAttachment();
|
|
3863
3970
|
SUBAGENT_CREATE_TOOL = "subagent_create";
|
|
3864
3971
|
SUBAGENT_MESSAGE_TOOL = "subagent_message";
|
|
3865
3972
|
SUBAGENTS_LIST_TOOL = "subagents";
|
|
@@ -4908,7 +5015,8 @@ Message one with subagent_message(referenceId, message).`
|
|
|
4908
5015
|
stub,
|
|
4909
5016
|
state.thread.instance,
|
|
4910
5017
|
childResult.attachments,
|
|
4911
|
-
`from-subagent-${childThreadId}
|
|
5018
|
+
`from-subagent-${childThreadId}`,
|
|
5019
|
+
state.env.AGENT_BUILDER_ATTACHMENT_FETCH_HOSTS
|
|
4912
5020
|
);
|
|
4913
5021
|
if (resumable) {
|
|
4914
5022
|
await this.settleResumableChildAfterRun(
|
|
@@ -4941,7 +5049,8 @@ Message one with subagent_message(referenceId, message).`
|
|
|
4941
5049
|
stub,
|
|
4942
5050
|
state.thread.instance,
|
|
4943
5051
|
childResult.attachments,
|
|
4944
|
-
`from-subagent-${childThreadId}
|
|
5052
|
+
`from-subagent-${childThreadId}`,
|
|
5053
|
+
state.env.AGENT_BUILDER_ATTACHMENT_FETCH_HOSTS
|
|
4945
5054
|
);
|
|
4946
5055
|
const messageContent = this.formatSubagentTerminalMessage(
|
|
4947
5056
|
childThreadId,
|
|
@@ -5355,7 +5464,8 @@ Message one with subagent_message(referenceId, message).`
|
|
|
5355
5464
|
state.thread.instance,
|
|
5356
5465
|
childThread,
|
|
5357
5466
|
parentAttachments,
|
|
5358
|
-
`from-parent-${state.threadId}
|
|
5467
|
+
`from-parent-${state.threadId}`,
|
|
5468
|
+
state.env.AGENT_BUILDER_ATTACHMENT_FETCH_HOSTS
|
|
5359
5469
|
);
|
|
5360
5470
|
const targetRole = receivesMessages === "side_a" ? "user" : "assistant";
|
|
5361
5471
|
const baseTimestamp = Date.now() * 1e3;
|
|
@@ -5615,7 +5725,7 @@ Reference: ${referenceId}` : `Reference: ${referenceId}`;
|
|
|
5615
5725
|
const shortId = crypto.randomUUID().slice(0, 8);
|
|
5616
5726
|
return `/attachments/${normalizedStem}-${shortId}.${finalExt}`;
|
|
5617
5727
|
}
|
|
5618
|
-
static async copyAttachmentsBetweenThreads(sourceThread, targetThread, attachments, _pathPrefix) {
|
|
5728
|
+
static async copyAttachmentsBetweenThreads(sourceThread, targetThread, attachments, _pathPrefix, allowedAttachmentFetchHosts) {
|
|
5619
5729
|
if (!attachments || attachments.length === 0) {
|
|
5620
5730
|
return [];
|
|
5621
5731
|
}
|
|
@@ -5643,7 +5753,8 @@ Reference: ${referenceId}` : `Reference: ${referenceId}`;
|
|
|
5643
5753
|
const copiedData = await this.readAttachmentDataFromSource(
|
|
5644
5754
|
sourceThread,
|
|
5645
5755
|
attachment.path,
|
|
5646
|
-
sourceFile
|
|
5756
|
+
sourceFile,
|
|
5757
|
+
allowedAttachmentFetchHosts
|
|
5647
5758
|
);
|
|
5648
5759
|
if (!copiedData) {
|
|
5649
5760
|
continue;
|
|
@@ -5700,7 +5811,7 @@ Reference: ${referenceId}` : `Reference: ${referenceId}`;
|
|
|
5700
5811
|
}
|
|
5701
5812
|
return copied;
|
|
5702
5813
|
}
|
|
5703
|
-
static async readAttachmentDataFromSource(sourceThread, path10, sourceFile) {
|
|
5814
|
+
static async readAttachmentDataFromSource(sourceThread, path10, sourceFile, allowedAttachmentFetchHosts) {
|
|
5704
5815
|
const sourceData = await sourceThread.readFile(path10);
|
|
5705
5816
|
if (sourceData.success && sourceData.data) {
|
|
5706
5817
|
return sourceData.data;
|
|
@@ -5709,14 +5820,17 @@ Reference: ${referenceId}` : `Reference: ${referenceId}`;
|
|
|
5709
5820
|
return null;
|
|
5710
5821
|
}
|
|
5711
5822
|
const location = sourceFile.location;
|
|
5712
|
-
if (!location
|
|
5823
|
+
if (!location) {
|
|
5824
|
+
return null;
|
|
5825
|
+
}
|
|
5826
|
+
const response = await fetchRemoteAttachment(
|
|
5827
|
+
location,
|
|
5828
|
+
allowedAttachmentFetchHosts
|
|
5829
|
+
);
|
|
5830
|
+
if (!response) {
|
|
5713
5831
|
return null;
|
|
5714
5832
|
}
|
|
5715
5833
|
try {
|
|
5716
|
-
const response = await fetch(location);
|
|
5717
|
-
if (!response.ok) {
|
|
5718
|
-
return null;
|
|
5719
|
-
}
|
|
5720
5834
|
const buffer = await response.arrayBuffer();
|
|
5721
5835
|
return this.arrayBufferToBase64(buffer);
|
|
5722
5836
|
} catch {
|
|
@@ -5970,7 +6084,8 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
|
|
|
5970
6084
|
state.thread.instance,
|
|
5971
6085
|
childStub,
|
|
5972
6086
|
sourceAttachments,
|
|
5973
|
-
`from-parent-${state.threadId}
|
|
6087
|
+
`from-parent-${state.threadId}`,
|
|
6088
|
+
state.env.AGENT_BUILDER_ATTACHMENT_FETCH_HOSTS
|
|
5974
6089
|
);
|
|
5975
6090
|
await childStub.queueMessage(referenceId, {
|
|
5976
6091
|
role: receivesMessages === "side_a" ? "user" : "assistant",
|
|
@@ -12570,6 +12685,32 @@ var ThreadStateImpl_exports = {};
|
|
|
12570
12685
|
__export(ThreadStateImpl_exports, {
|
|
12571
12686
|
ThreadStateImpl: () => ThreadStateImpl
|
|
12572
12687
|
});
|
|
12688
|
+
function isRuntimeDurableNamespace(value) {
|
|
12689
|
+
return value !== null && typeof value === "object" && "idFromName" in value && typeof value.idFromName === "function" && "get" in value && typeof value.get === "function";
|
|
12690
|
+
}
|
|
12691
|
+
function isThreadStateRuntimeEnvironment(value) {
|
|
12692
|
+
return value !== null && typeof value === "object" && "AGENT_BUILDER" in value && isRuntimeDurableNamespace(value.AGENT_BUILDER) && (!("AGENT_BUILDER_USER_HUB" in value) || value.AGENT_BUILDER_USER_HUB === void 0 || isRuntimeDurableNamespace(value.AGENT_BUILDER_USER_HUB));
|
|
12693
|
+
}
|
|
12694
|
+
function confinedUserEndpointUrl(userId, endpoint) {
|
|
12695
|
+
const base = new URL(
|
|
12696
|
+
`https://user-hub/users/${encodeURIComponent(userId)}/endpoints/`
|
|
12697
|
+
);
|
|
12698
|
+
const relative4 = endpoint.replace(/^\/+/, "");
|
|
12699
|
+
let decoded;
|
|
12700
|
+
try {
|
|
12701
|
+
decoded = decodeURIComponent(relative4);
|
|
12702
|
+
} catch {
|
|
12703
|
+
throw new Error("Invalid user endpoint path: malformed percent encoding.");
|
|
12704
|
+
}
|
|
12705
|
+
if (decoded.includes("\\") || decoded.includes("?") || decoded.includes("#") || /[\u0000-\u001f\u007f]/.test(decoded) || decoded.split("/").some((segment) => segment === "." || segment === "..")) {
|
|
12706
|
+
throw new Error("Invalid user endpoint path: traversal and URL syntax are not allowed.");
|
|
12707
|
+
}
|
|
12708
|
+
const resolved = new URL(relative4, base);
|
|
12709
|
+
if (resolved.origin !== base.origin || !resolved.pathname.startsWith(base.pathname)) {
|
|
12710
|
+
throw new Error("Invalid user endpoint path: endpoint escaped the user namespace.");
|
|
12711
|
+
}
|
|
12712
|
+
return resolved.toString();
|
|
12713
|
+
}
|
|
12573
12714
|
function hasLocalCodeExecutionRuntime(threadInstance) {
|
|
12574
12715
|
const candidate = threadInstance;
|
|
12575
12716
|
return Boolean(candidate.env && candidate.ctx);
|
|
@@ -12750,6 +12891,7 @@ function runCodeViaThreadRpc(threadInstance, threadId, source, options) {
|
|
|
12750
12891
|
var ThreadStateImpl, ExecutionStateImpl;
|
|
12751
12892
|
var init_ThreadStateImpl = __esm({
|
|
12752
12893
|
"src/agents/ThreadStateImpl.ts"() {
|
|
12894
|
+
init_scope();
|
|
12753
12895
|
init_client_forwarding();
|
|
12754
12896
|
init_types();
|
|
12755
12897
|
init_utilities();
|
|
@@ -12983,6 +13125,14 @@ var init_ThreadStateImpl = __esm({
|
|
|
12983
13125
|
}
|
|
12984
13126
|
return value;
|
|
12985
13127
|
}
|
|
13128
|
+
async instanceEnv(propertyName) {
|
|
13129
|
+
const agentBuilder = this._getAgentBuilderStub();
|
|
13130
|
+
if (typeof agentBuilder.getInstanceEnv !== "function") {
|
|
13131
|
+
throw new Error("instanceEnv is not supported by this runtime");
|
|
13132
|
+
}
|
|
13133
|
+
const values = await agentBuilder.getInstanceEnv();
|
|
13134
|
+
return values[propertyName];
|
|
13135
|
+
}
|
|
12986
13136
|
async envType(propertyName) {
|
|
12987
13137
|
const agentBuilder = this._getAgentBuilderStub();
|
|
12988
13138
|
if (typeof agentBuilder.resolveThreadEnvType === "function") {
|
|
@@ -14013,12 +14163,11 @@ var init_ThreadStateImpl = __esm({
|
|
|
14013
14163
|
* dispatcher recorded in the runtime context instead.
|
|
14014
14164
|
*/
|
|
14015
14165
|
_getRuntimeEnv() {
|
|
14016
|
-
|
|
14017
|
-
|
|
14018
|
-
return contextEnv;
|
|
14166
|
+
if (isThreadStateRuntimeEnvironment(this._runtimeContext.env)) {
|
|
14167
|
+
return this._runtimeContext.env;
|
|
14019
14168
|
}
|
|
14020
14169
|
const instanceEnv = this._threadInstance.env;
|
|
14021
|
-
if (!instanceEnv
|
|
14170
|
+
if (!isThreadStateRuntimeEnvironment(instanceEnv)) {
|
|
14022
14171
|
throw new Error(
|
|
14023
14172
|
"No runtime environment available on this ThreadState. Stub-backed states must be constructed with runtimeContext.env."
|
|
14024
14173
|
);
|
|
@@ -14035,9 +14184,7 @@ var init_ThreadStateImpl = __esm({
|
|
|
14035
14184
|
return namespace.get(namespace.idFromName(userId));
|
|
14036
14185
|
}
|
|
14037
14186
|
// ─────────────────────────────────────────────────────────────────────────
|
|
14038
|
-
// Skills —
|
|
14039
|
-
// DurableAgentBuilder singleton (skills are never stored per-thread or on
|
|
14040
|
-
// a client machine).
|
|
14187
|
+
// Skills — owner-scoped library plus explicitly shared administrator skills.
|
|
14041
14188
|
// ─────────────────────────────────────────────────────────────────────────
|
|
14042
14189
|
/**
|
|
14043
14190
|
* The profile of the user this thread belongs to (identity fields only —
|
|
@@ -14060,9 +14207,8 @@ var init_ThreadStateImpl = __esm({
|
|
|
14060
14207
|
"Reentrant user-scope call: this ThreadState was raised from user-scope code; state.user().call() is unavailable here."
|
|
14061
14208
|
);
|
|
14062
14209
|
}
|
|
14063
|
-
const path10 = endpoint.replace(/^\/+/, "");
|
|
14064
14210
|
return hub().fetch(
|
|
14065
|
-
new Request(
|
|
14211
|
+
new Request(confinedUserEndpointUrl(userId, endpoint), {
|
|
14066
14212
|
method: "POST",
|
|
14067
14213
|
headers: {
|
|
14068
14214
|
"Content-Type": "application/json",
|
|
@@ -14122,18 +14268,42 @@ var init_ThreadStateImpl = __esm({
|
|
|
14122
14268
|
}
|
|
14123
14269
|
get skills() {
|
|
14124
14270
|
const stub = this._getAgentBuilderStub();
|
|
14271
|
+
const ownerId = this._metadata.user_id ?? SHARED_SKILL_OWNER;
|
|
14272
|
+
const scope = {
|
|
14273
|
+
ownerId,
|
|
14274
|
+
includeShared: ownerId !== SHARED_SKILL_OWNER
|
|
14275
|
+
};
|
|
14276
|
+
const requireMutationAdmin = async () => {
|
|
14277
|
+
const userId = this._metadata.user_id;
|
|
14278
|
+
if (!userId) {
|
|
14279
|
+
throw new Error("Skill mutations require an authenticated instance admin.");
|
|
14280
|
+
}
|
|
14281
|
+
const user = await stub.getUserById(userId);
|
|
14282
|
+
if (user?.role !== "admin") {
|
|
14283
|
+
throw new Error("Skill mutations require an instance admin.");
|
|
14284
|
+
}
|
|
14285
|
+
};
|
|
14125
14286
|
return {
|
|
14126
|
-
list: (options) => stub.listSkills(options),
|
|
14287
|
+
list: (options) => stub.listSkills(scope, options),
|
|
14127
14288
|
get: async (name15) => {
|
|
14128
|
-
const metadata = await stub.getSkill(name15);
|
|
14289
|
+
const metadata = await stub.getSkill(scope, name15);
|
|
14129
14290
|
if (!metadata) return null;
|
|
14130
|
-
const skillMd = await stub.getSkillFile(name15, "SKILL.md") ?? "";
|
|
14291
|
+
const skillMd = await stub.getSkillFile(scope, name15, "SKILL.md") ?? "";
|
|
14131
14292
|
return { metadata, skillMd };
|
|
14132
14293
|
},
|
|
14133
|
-
readFile: (name15, path10) => stub.getSkillFile(name15, path10),
|
|
14134
|
-
install: (files) =>
|
|
14135
|
-
|
|
14136
|
-
|
|
14294
|
+
readFile: (name15, path10) => stub.getSkillFile(scope, name15, path10),
|
|
14295
|
+
install: async (files) => {
|
|
14296
|
+
await requireMutationAdmin();
|
|
14297
|
+
return stub.upsertSkill(scope, files);
|
|
14298
|
+
},
|
|
14299
|
+
setEnabled: async (name15, enabled) => {
|
|
14300
|
+
await requireMutationAdmin();
|
|
14301
|
+
return stub.setSkillEnabled(scope, name15, enabled);
|
|
14302
|
+
},
|
|
14303
|
+
remove: async (name15) => {
|
|
14304
|
+
await requireMutationAdmin();
|
|
14305
|
+
return stub.deleteSkill(scope, name15);
|
|
14306
|
+
}
|
|
14137
14307
|
};
|
|
14138
14308
|
}
|
|
14139
14309
|
// ─────────────────────────────────────────────────────────────────────────
|
|
@@ -67052,6 +67222,7 @@ function getParamRegexp(segment) {
|
|
|
67052
67222
|
init_ThreadStateImpl();
|
|
67053
67223
|
|
|
67054
67224
|
// src/utils/auth.ts
|
|
67225
|
+
var SUPER_ADMIN_TOKEN_TTL_SECONDS = 12 * 60 * 60;
|
|
67055
67226
|
function generateSecureToken(length = 32) {
|
|
67056
67227
|
const array44 = new Uint8Array(length);
|
|
67057
67228
|
crypto.getRandomValues(array44);
|
|
@@ -67063,6 +67234,20 @@ function generateUserToken() {
|
|
|
67063
67234
|
function generateApiKey() {
|
|
67064
67235
|
return `agtbldr_${generateSecureToken(32)}`;
|
|
67065
67236
|
}
|
|
67237
|
+
async function constantTimeEqual(left, right) {
|
|
67238
|
+
const encoder2 = new TextEncoder();
|
|
67239
|
+
const [leftDigest, rightDigest] = await Promise.all([
|
|
67240
|
+
crypto.subtle.digest("SHA-256", encoder2.encode(left)),
|
|
67241
|
+
crypto.subtle.digest("SHA-256", encoder2.encode(right))
|
|
67242
|
+
]);
|
|
67243
|
+
const leftBytes = new Uint8Array(leftDigest);
|
|
67244
|
+
const rightBytes = new Uint8Array(rightDigest);
|
|
67245
|
+
let difference = 0;
|
|
67246
|
+
for (let index = 0; index < leftBytes.length; index++) {
|
|
67247
|
+
difference |= leftBytes[index] ^ rightBytes[index];
|
|
67248
|
+
}
|
|
67249
|
+
return difference === 0;
|
|
67250
|
+
}
|
|
67066
67251
|
async function hashPassword(password) {
|
|
67067
67252
|
const encoder2 = new TextEncoder();
|
|
67068
67253
|
const data = encoder2.encode(password);
|
|
@@ -67174,9 +67359,9 @@ function isValidUserToken(token) {
|
|
|
67174
67359
|
function isValidApiKey(key) {
|
|
67175
67360
|
return key.startsWith("agtbldr_") && key.length > 10 || key.startsWith("sak_live_") && key.length > 10;
|
|
67176
67361
|
}
|
|
67177
|
-
async function signToken(payload,
|
|
67362
|
+
async function signToken(payload, encryptionKey2) {
|
|
67178
67363
|
const encoder2 = new TextEncoder();
|
|
67179
|
-
const keyData = encoder2.encode(
|
|
67364
|
+
const keyData = encoder2.encode(encryptionKey2);
|
|
67180
67365
|
const cryptoKey = await crypto.subtle.importKey(
|
|
67181
67366
|
"raw",
|
|
67182
67367
|
keyData,
|
|
@@ -67190,7 +67375,7 @@ async function signToken(payload, encryptionKey) {
|
|
|
67190
67375
|
const signatureB64 = bufferToBase64(new Uint8Array(signature));
|
|
67191
67376
|
return `${payloadB64}.${signatureB64}`;
|
|
67192
67377
|
}
|
|
67193
|
-
async function verifySignedToken(signedToken,
|
|
67378
|
+
async function verifySignedToken(signedToken, encryptionKey2) {
|
|
67194
67379
|
try {
|
|
67195
67380
|
const parts = signedToken.split(".");
|
|
67196
67381
|
if (parts.length !== 2) {
|
|
@@ -67198,7 +67383,7 @@ async function verifySignedToken(signedToken, encryptionKey) {
|
|
|
67198
67383
|
}
|
|
67199
67384
|
const [payloadB64, signatureB64] = parts;
|
|
67200
67385
|
const encoder2 = new TextEncoder();
|
|
67201
|
-
const keyData = encoder2.encode(
|
|
67386
|
+
const keyData = encoder2.encode(encryptionKey2);
|
|
67202
67387
|
const cryptoKey = await crypto.subtle.importKey(
|
|
67203
67388
|
"raw",
|
|
67204
67389
|
keyData,
|
|
@@ -67219,14 +67404,14 @@ async function verifySignedToken(signedToken, encryptionKey) {
|
|
|
67219
67404
|
return null;
|
|
67220
67405
|
}
|
|
67221
67406
|
}
|
|
67222
|
-
async function generateSuperAdminToken(
|
|
67407
|
+
async function generateSuperAdminToken(encryptionKey2) {
|
|
67223
67408
|
const timestamp = Date.now();
|
|
67224
67409
|
const nonce = generateSecureToken(16);
|
|
67225
67410
|
const payload = `super_admin:${timestamp}:${nonce}`;
|
|
67226
|
-
return await signToken(payload,
|
|
67411
|
+
return await signToken(payload, encryptionKey2);
|
|
67227
67412
|
}
|
|
67228
|
-
async function verifySuperAdminToken(token,
|
|
67229
|
-
const payload = await verifySignedToken(token,
|
|
67413
|
+
async function verifySuperAdminToken(token, encryptionKey2) {
|
|
67414
|
+
const payload = await verifySignedToken(token, encryptionKey2);
|
|
67230
67415
|
if (!payload) {
|
|
67231
67416
|
return false;
|
|
67232
67417
|
}
|
|
@@ -67235,9 +67420,12 @@ async function verifySuperAdminToken(token, encryptionKey) {
|
|
|
67235
67420
|
return false;
|
|
67236
67421
|
}
|
|
67237
67422
|
const timestamp = parseInt(parts[1], 10);
|
|
67423
|
+
if (!Number.isFinite(timestamp)) {
|
|
67424
|
+
return false;
|
|
67425
|
+
}
|
|
67238
67426
|
const age = Date.now() - timestamp;
|
|
67239
|
-
const maxAge =
|
|
67240
|
-
if (age > maxAge) {
|
|
67427
|
+
const maxAge = SUPER_ADMIN_TOKEN_TTL_SECONDS * 1e3;
|
|
67428
|
+
if (age < 0 || age > maxAge) {
|
|
67241
67429
|
return false;
|
|
67242
67430
|
}
|
|
67243
67431
|
return true;
|
|
@@ -67258,17 +67446,99 @@ function base64ToBuffer(base64) {
|
|
|
67258
67446
|
return bytes;
|
|
67259
67447
|
}
|
|
67260
67448
|
|
|
67261
|
-
// src/
|
|
67262
|
-
|
|
67449
|
+
// src/routing/access-policy.ts
|
|
67450
|
+
function isHostedInstance(env2) {
|
|
67451
|
+
const value = env2 && typeof env2 === "object" ? Reflect.get(env2, "STANDARD_AGENTS_HOSTED") : void 0;
|
|
67452
|
+
if (typeof value === "string") {
|
|
67453
|
+
const normalized = value.trim().toLowerCase();
|
|
67454
|
+
return normalized !== "" && normalized !== "0" && normalized !== "false";
|
|
67455
|
+
}
|
|
67456
|
+
return Boolean(value);
|
|
67457
|
+
}
|
|
67458
|
+
function isTrustedLocalDevelopmentRequest(request, env2) {
|
|
67459
|
+
if (isHostedInstance(env2)) return false;
|
|
67460
|
+
let hostname;
|
|
67461
|
+
try {
|
|
67462
|
+
hostname = new URL(request.url).hostname.toLowerCase();
|
|
67463
|
+
} catch {
|
|
67464
|
+
return false;
|
|
67465
|
+
}
|
|
67466
|
+
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname.endsWith(".localhost") || hostname.endsWith(".orb.local");
|
|
67467
|
+
}
|
|
67468
|
+
function requestObservedOrigins(request) {
|
|
67469
|
+
const origins = /* @__PURE__ */ new Set();
|
|
67470
|
+
let url = null;
|
|
67471
|
+
try {
|
|
67472
|
+
url = new URL(request.url);
|
|
67473
|
+
origins.add(url.origin);
|
|
67474
|
+
} catch {
|
|
67475
|
+
url = null;
|
|
67476
|
+
}
|
|
67477
|
+
const forwardedHost = request.headers.get("x-forwarded-host")?.split(",")[0]?.trim();
|
|
67478
|
+
const host = forwardedHost || request.headers.get("host")?.trim();
|
|
67479
|
+
if (!host) return origins;
|
|
67480
|
+
const forwardedProto = request.headers.get("x-forwarded-proto")?.split(",")[0]?.trim().toLowerCase();
|
|
67481
|
+
const schemes = /* @__PURE__ */ new Set();
|
|
67482
|
+
if (forwardedProto === "http" || forwardedProto === "https") schemes.add(forwardedProto);
|
|
67483
|
+
if (url) schemes.add(url.protocol.replace(":", ""));
|
|
67484
|
+
if (schemes.size === 0) {
|
|
67485
|
+
schemes.add(host.endsWith(".orb.local") ? "https" : "http");
|
|
67486
|
+
}
|
|
67487
|
+
for (const scheme of schemes) {
|
|
67488
|
+
try {
|
|
67489
|
+
origins.add(new URL(`${scheme}://${host}`).origin);
|
|
67490
|
+
} catch {
|
|
67491
|
+
}
|
|
67492
|
+
}
|
|
67493
|
+
return origins;
|
|
67494
|
+
}
|
|
67495
|
+
function isSameOriginBrowserRequest(request) {
|
|
67496
|
+
const fetchSite = request.headers.get("Sec-Fetch-Site")?.trim().toLowerCase();
|
|
67497
|
+
if (fetchSite === "same-origin" || fetchSite === "none") {
|
|
67498
|
+
return true;
|
|
67499
|
+
}
|
|
67500
|
+
if (fetchSite) {
|
|
67501
|
+
return false;
|
|
67502
|
+
}
|
|
67503
|
+
const origin = request.headers.get("Origin")?.trim();
|
|
67504
|
+
if (!origin) return true;
|
|
67505
|
+
if (origin === "null") return false;
|
|
67506
|
+
try {
|
|
67507
|
+
return requestObservedOrigins(request).has(new URL(origin).origin);
|
|
67508
|
+
} catch {
|
|
67509
|
+
return false;
|
|
67510
|
+
}
|
|
67511
|
+
}
|
|
67512
|
+
|
|
67513
|
+
// src/routing/cors.ts
|
|
67514
|
+
var RUNTIME_CORS_HEADERS = {
|
|
67263
67515
|
"Access-Control-Allow-Origin": "*",
|
|
67264
67516
|
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
|
|
67265
67517
|
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With",
|
|
67266
67518
|
"Access-Control-Max-Age": "86400"
|
|
67267
67519
|
};
|
|
67268
|
-
function
|
|
67520
|
+
function exposesRuntimeCors(request, env2) {
|
|
67521
|
+
return !isTrustedLocalDevelopmentRequest(request, env2);
|
|
67522
|
+
}
|
|
67523
|
+
function runtimeCorsHeaders(request, env2) {
|
|
67524
|
+
return exposesRuntimeCors(request, env2) ? { ...RUNTIME_CORS_HEADERS } : {};
|
|
67525
|
+
}
|
|
67526
|
+
|
|
67527
|
+
// src/middleware/auth.ts
|
|
67528
|
+
function isAuthenticationEnv(env2) {
|
|
67529
|
+
if (!env2 || typeof env2 !== "object") return false;
|
|
67530
|
+
const namespace = env2.AGENT_BUILDER;
|
|
67531
|
+
return !!namespace && typeof namespace === "object" && typeof namespace.idFromName === "function" && typeof namespace.get === "function";
|
|
67532
|
+
}
|
|
67533
|
+
function hasPermission(user, permission, options = {}) {
|
|
67269
67534
|
if (user.role === "admin") return true;
|
|
67270
67535
|
if (Array.isArray(user.permissions)) return user.permissions.includes(permission);
|
|
67271
|
-
return user.role
|
|
67536
|
+
return options.allowLegacyUserFallback !== false && user.role === "user";
|
|
67537
|
+
}
|
|
67538
|
+
function hasPermissionInEnvironment(user, permission, env2) {
|
|
67539
|
+
return hasPermission(user, permission, {
|
|
67540
|
+
allowLegacyUserFallback: !isHostedInstance(env2)
|
|
67541
|
+
});
|
|
67272
67542
|
}
|
|
67273
67543
|
function parsePermissions(value) {
|
|
67274
67544
|
if (Array.isArray(value)) return value.filter((p) => typeof p === "string");
|
|
@@ -67290,43 +67560,96 @@ function extractBearerToken(request) {
|
|
|
67290
67560
|
if (cookieToken) {
|
|
67291
67561
|
return cookieToken;
|
|
67292
67562
|
}
|
|
67293
|
-
const isWebSocket = request.headers.get("upgrade")?.toLowerCase() === "websocket";
|
|
67294
|
-
if (isWebSocket) {
|
|
67295
|
-
try {
|
|
67296
|
-
const url = new URL(request.url);
|
|
67297
|
-
const token = url.searchParams.get("token");
|
|
67298
|
-
if (token) {
|
|
67299
|
-
return token;
|
|
67300
|
-
}
|
|
67301
|
-
} catch (err) {
|
|
67302
|
-
}
|
|
67303
|
-
}
|
|
67304
67563
|
return null;
|
|
67305
67564
|
}
|
|
67306
67565
|
function getAgentBuilder(env2) {
|
|
67307
67566
|
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
67308
67567
|
return env2.AGENT_BUILDER.get(agentBuilderId);
|
|
67309
67568
|
}
|
|
67569
|
+
function parseWebSocketTicketAuth(authJson) {
|
|
67570
|
+
let parsed;
|
|
67571
|
+
try {
|
|
67572
|
+
parsed = JSON.parse(authJson);
|
|
67573
|
+
} catch {
|
|
67574
|
+
return null;
|
|
67575
|
+
}
|
|
67576
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
67577
|
+
const record24 = parsed;
|
|
67578
|
+
if (!record24.user || typeof record24.user !== "object") return null;
|
|
67579
|
+
const user = record24.user;
|
|
67580
|
+
if (typeof user.id !== "string" || typeof user.username !== "string" || typeof user.role !== "string" || record24.authType !== "super_admin" && record24.authType !== "session" && record24.authType !== "api_key") {
|
|
67581
|
+
return null;
|
|
67582
|
+
}
|
|
67583
|
+
const permissions = user.permissions;
|
|
67584
|
+
if (permissions !== void 0 && permissions !== null && (!Array.isArray(permissions) || !permissions.every((permission) => typeof permission === "string"))) {
|
|
67585
|
+
return null;
|
|
67586
|
+
}
|
|
67587
|
+
if (record24.credentialId !== void 0 && typeof record24.credentialId !== "string") return null;
|
|
67588
|
+
return {
|
|
67589
|
+
user: {
|
|
67590
|
+
id: user.id,
|
|
67591
|
+
username: user.username,
|
|
67592
|
+
role: user.role,
|
|
67593
|
+
permissions,
|
|
67594
|
+
platform_user_id: typeof user.platform_user_id === "string" ? user.platform_user_id : null,
|
|
67595
|
+
email: typeof user.email === "string" ? user.email : null,
|
|
67596
|
+
display_name: typeof user.display_name === "string" ? user.display_name : null,
|
|
67597
|
+
avatar_url: typeof user.avatar_url === "string" ? user.avatar_url : null
|
|
67598
|
+
},
|
|
67599
|
+
authType: record24.authType,
|
|
67600
|
+
credentialId: record24.credentialId
|
|
67601
|
+
};
|
|
67602
|
+
}
|
|
67603
|
+
async function consumeWebSocketTicket(request, env2) {
|
|
67604
|
+
if (request.headers.get("upgrade")?.toLowerCase() !== "websocket") return null;
|
|
67605
|
+
let url;
|
|
67606
|
+
try {
|
|
67607
|
+
url = new URL(request.url);
|
|
67608
|
+
} catch {
|
|
67609
|
+
return null;
|
|
67610
|
+
}
|
|
67611
|
+
const ticket = url.searchParams.get("ticket");
|
|
67612
|
+
if (!ticket) return null;
|
|
67613
|
+
const authJson = await getAgentBuilder(env2).consumeWebSocketTicket({
|
|
67614
|
+
ticket_hash: await hashToken(ticket),
|
|
67615
|
+
pathname: url.pathname
|
|
67616
|
+
});
|
|
67617
|
+
return typeof authJson === "string" ? parseWebSocketTicketAuth(authJson) : null;
|
|
67618
|
+
}
|
|
67619
|
+
function isWebSocketTicketPath(pathname) {
|
|
67620
|
+
if (!pathname.startsWith("/api/") || pathname.includes("?") || pathname.includes("#")) return false;
|
|
67621
|
+
try {
|
|
67622
|
+
return new URL(pathname, "https://runtime.invalid").pathname === pathname;
|
|
67623
|
+
} catch {
|
|
67624
|
+
return false;
|
|
67625
|
+
}
|
|
67626
|
+
}
|
|
67310
67627
|
async function authenticate(request, env2) {
|
|
67628
|
+
const ticketAuth = await consumeWebSocketTicket(request, env2);
|
|
67629
|
+
if (ticketAuth) return ticketAuth;
|
|
67311
67630
|
const token = extractBearerToken(request);
|
|
67312
67631
|
if (!token) {
|
|
67313
67632
|
return null;
|
|
67314
67633
|
}
|
|
67315
|
-
if (env2.SUPER_ADMIN_PASSWORD && env2.ENCRYPTION_KEY) {
|
|
67634
|
+
if (typeof env2.SUPER_ADMIN_PASSWORD === "string" && typeof env2.ENCRYPTION_KEY === "string") {
|
|
67316
67635
|
if (token.includes(".")) {
|
|
67317
67636
|
const isValidSuperAdmin = await verifySuperAdminToken(
|
|
67318
67637
|
token,
|
|
67319
67638
|
env2.ENCRYPTION_KEY
|
|
67320
67639
|
);
|
|
67321
67640
|
if (isValidSuperAdmin) {
|
|
67322
|
-
|
|
67323
|
-
|
|
67324
|
-
|
|
67325
|
-
|
|
67326
|
-
|
|
67327
|
-
|
|
67328
|
-
|
|
67329
|
-
|
|
67641
|
+
const tokenHash = await hashToken(token);
|
|
67642
|
+
const agentBuilder = getAgentBuilder(env2);
|
|
67643
|
+
if (await agentBuilder.validateSuperAdminSession(tokenHash)) {
|
|
67644
|
+
return {
|
|
67645
|
+
user: {
|
|
67646
|
+
id: "super_admin",
|
|
67647
|
+
username: "admin",
|
|
67648
|
+
role: "admin"
|
|
67649
|
+
},
|
|
67650
|
+
authType: "super_admin"
|
|
67651
|
+
};
|
|
67652
|
+
}
|
|
67330
67653
|
}
|
|
67331
67654
|
}
|
|
67332
67655
|
}
|
|
@@ -67371,7 +67694,8 @@ async function authenticate(request, env2) {
|
|
|
67371
67694
|
display_name: user.display_name ?? null,
|
|
67372
67695
|
avatar_url: user.avatar_url ?? null
|
|
67373
67696
|
},
|
|
67374
|
-
authType: "api_key"
|
|
67697
|
+
authType: "api_key",
|
|
67698
|
+
credentialId: apiKey.id
|
|
67375
67699
|
};
|
|
67376
67700
|
}
|
|
67377
67701
|
}
|
|
@@ -67383,7 +67707,10 @@ async function requireAuth(request, env2) {
|
|
|
67383
67707
|
if (!authContext) {
|
|
67384
67708
|
return new Response(JSON.stringify({ error: "Unauthorized" }), {
|
|
67385
67709
|
status: 401,
|
|
67386
|
-
headers: {
|
|
67710
|
+
headers: {
|
|
67711
|
+
"Content-Type": "application/json",
|
|
67712
|
+
...runtimeCorsHeaders(request, env2)
|
|
67713
|
+
}
|
|
67387
67714
|
});
|
|
67388
67715
|
}
|
|
67389
67716
|
return authContext;
|
|
@@ -67393,12 +67720,15 @@ async function requirePermission(request, env2, permission) {
|
|
|
67393
67720
|
if (result instanceof Response) {
|
|
67394
67721
|
return result;
|
|
67395
67722
|
}
|
|
67396
|
-
if (!
|
|
67723
|
+
if (!hasPermissionInEnvironment(result.user, permission, env2)) {
|
|
67397
67724
|
return new Response(
|
|
67398
67725
|
JSON.stringify({ error: `Forbidden: '${permission}' access required` }),
|
|
67399
67726
|
{
|
|
67400
67727
|
status: 403,
|
|
67401
|
-
headers: {
|
|
67728
|
+
headers: {
|
|
67729
|
+
"Content-Type": "application/json",
|
|
67730
|
+
...runtimeCorsHeaders(request, env2)
|
|
67731
|
+
}
|
|
67402
67732
|
}
|
|
67403
67733
|
);
|
|
67404
67734
|
}
|
|
@@ -67414,7 +67744,10 @@ async function requireAdmin(request, env2) {
|
|
|
67414
67744
|
JSON.stringify({ error: "Forbidden: Admin access required" }),
|
|
67415
67745
|
{
|
|
67416
67746
|
status: 403,
|
|
67417
|
-
headers: {
|
|
67747
|
+
headers: {
|
|
67748
|
+
"Content-Type": "application/json",
|
|
67749
|
+
...runtimeCorsHeaders(request, env2)
|
|
67750
|
+
}
|
|
67418
67751
|
}
|
|
67419
67752
|
);
|
|
67420
67753
|
}
|
|
@@ -67424,27 +67757,6 @@ function defineController2(controller) {
|
|
|
67424
67757
|
return controller;
|
|
67425
67758
|
}
|
|
67426
67759
|
|
|
67427
|
-
// src/api/index.post.ts
|
|
67428
|
-
var index_post_default = defineController2(() => {
|
|
67429
|
-
const stream = new ReadableStream({
|
|
67430
|
-
start(controller) {
|
|
67431
|
-
const text2 = "hello world";
|
|
67432
|
-
let index = 0;
|
|
67433
|
-
const next = () => {
|
|
67434
|
-
if (index < text2.length) {
|
|
67435
|
-
controller.enqueue(new TextEncoder().encode(text2[index]));
|
|
67436
|
-
index++;
|
|
67437
|
-
setTimeout(next, 100);
|
|
67438
|
-
} else {
|
|
67439
|
-
controller.close();
|
|
67440
|
-
}
|
|
67441
|
-
};
|
|
67442
|
-
next();
|
|
67443
|
-
}
|
|
67444
|
-
});
|
|
67445
|
-
return new Response(stream);
|
|
67446
|
-
});
|
|
67447
|
-
|
|
67448
67760
|
// src/api/agents.get.ts
|
|
67449
67761
|
var agents_get_default = defineController2(async ({ agents, agentNames, registry, auth }) => {
|
|
67450
67762
|
const includeAuthoringDetails = auth?.user.role === "admin";
|
|
@@ -67526,29 +67838,16 @@ var agents_get_default = defineController2(async ({ agents, agentNames, registry
|
|
|
67526
67838
|
return Response.json({ agents: validAgents });
|
|
67527
67839
|
});
|
|
67528
67840
|
|
|
67529
|
-
// src/routing/access-policy.ts
|
|
67530
|
-
function isHostedInstance(env2) {
|
|
67531
|
-
const value = env2?.STANDARD_AGENTS_HOSTED;
|
|
67532
|
-
if (typeof value === "string") {
|
|
67533
|
-
const normalized = value.trim().toLowerCase();
|
|
67534
|
-
return normalized !== "" && normalized !== "0" && normalized !== "false";
|
|
67535
|
-
}
|
|
67536
|
-
return Boolean(value);
|
|
67537
|
-
}
|
|
67538
|
-
function isTrustedLocalDevelopmentRequest(request, env2) {
|
|
67539
|
-
if (isHostedInstance(env2)) return false;
|
|
67540
|
-
let hostname;
|
|
67541
|
-
try {
|
|
67542
|
-
hostname = new URL(request.url).hostname.toLowerCase();
|
|
67543
|
-
} catch {
|
|
67544
|
-
return false;
|
|
67545
|
-
}
|
|
67546
|
-
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname.endsWith(".localhost") || hostname.endsWith(".orb.local");
|
|
67547
|
-
}
|
|
67548
|
-
|
|
67549
67841
|
// src/utils/platform-auth.ts
|
|
67550
67842
|
var FALLBACK_PLATFORM_ORIGIN = "https://platform.standardagents.ai";
|
|
67551
67843
|
var SESSION_TTL_SECONDS = 30 * 24 * 60 * 60;
|
|
67844
|
+
function agentBuilderAuthStub(env2) {
|
|
67845
|
+
const namespace = env2.AGENT_BUILDER;
|
|
67846
|
+
if (!namespace || typeof namespace.idFromName !== "function" || typeof namespace.get !== "function") {
|
|
67847
|
+
throw new Error("Server misconfigured: AGENT_BUILDER Durable Object binding is required for platform auth");
|
|
67848
|
+
}
|
|
67849
|
+
return namespace.get(namespace.idFromName("singleton"));
|
|
67850
|
+
}
|
|
67552
67851
|
function platformApiKey(env2) {
|
|
67553
67852
|
const value = env2.STANDARD_AGENTS_API_KEY;
|
|
67554
67853
|
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
@@ -67707,11 +68006,7 @@ async function getPlatformIdentity(env2) {
|
|
|
67707
68006
|
};
|
|
67708
68007
|
}
|
|
67709
68008
|
async function upsertReplicaUserForPlatformProfile(env2, profile) {
|
|
67710
|
-
const
|
|
67711
|
-
if (!namespace || typeof namespace.idFromName !== "function" || typeof namespace.get !== "function") {
|
|
67712
|
-
throw new Error("Server misconfigured: AGENT_BUILDER Durable Object binding is required for platform auth");
|
|
67713
|
-
}
|
|
67714
|
-
const agentBuilder = namespace.get(namespace.idFromName("singleton"));
|
|
68009
|
+
const agentBuilder = agentBuilderAuthStub(env2);
|
|
67715
68010
|
return await agentBuilder.upsertPlatformReplicaUser({
|
|
67716
68011
|
platform_user_id: profile.platform_user_id,
|
|
67717
68012
|
username: profile.username ?? null,
|
|
@@ -67723,11 +68018,7 @@ async function upsertReplicaUserForPlatformProfile(env2, profile) {
|
|
|
67723
68018
|
});
|
|
67724
68019
|
}
|
|
67725
68020
|
async function mintLocalSessionForPlatformUser(env2, platformUser) {
|
|
67726
|
-
const
|
|
67727
|
-
if (!namespace || typeof namespace.idFromName !== "function" || typeof namespace.get !== "function") {
|
|
67728
|
-
throw new Error("Server misconfigured: AGENT_BUILDER Durable Object binding is required for platform auth");
|
|
67729
|
-
}
|
|
67730
|
-
const agentBuilder = namespace.get(namespace.idFromName("singleton"));
|
|
68021
|
+
const agentBuilder = agentBuilderAuthStub(env2);
|
|
67731
68022
|
const profile = typeof platformUser === "string" ? { platform_user_id: platformUser, username: `sa-${platformUser.slice(0, 12)}`, role: "admin" } : platformUser;
|
|
67732
68023
|
const user = await upsertReplicaUserForPlatformProfile(env2, profile);
|
|
67733
68024
|
if (user.role === "api") {
|
|
@@ -67739,6 +68030,12 @@ async function mintLocalSessionForPlatformUser(env2, platformUser) {
|
|
|
67739
68030
|
await agentBuilder.createSession({ user_id: user.id, token_hash: tokenHash, expires_at: expiresAt });
|
|
67740
68031
|
return { token, user: { id: user.id, username: user.username, role: user.role } };
|
|
67741
68032
|
}
|
|
68033
|
+
async function consumePlatformHandoffJti(env2, jti, expiresAt) {
|
|
68034
|
+
return agentBuilderAuthStub(env2).consumePlatformHandoffJti({
|
|
68035
|
+
jti,
|
|
68036
|
+
expires_at: expiresAt
|
|
68037
|
+
});
|
|
68038
|
+
}
|
|
67742
68039
|
async function createPlatformLocalSession(request, env2) {
|
|
67743
68040
|
if (!isTrustedLocalDevelopmentRequest(request, env2)) {
|
|
67744
68041
|
return null;
|
|
@@ -67752,12 +68049,7 @@ async function createPlatformLocalSession(request, env2) {
|
|
|
67752
68049
|
if (!identity) {
|
|
67753
68050
|
throw new Error("STANDARD_AGENTS_API_KEY could not be resolved to one active user-instance membership.");
|
|
67754
68051
|
}
|
|
67755
|
-
const
|
|
67756
|
-
if (!agentBuilderNamespace || typeof agentBuilderNamespace.idFromName !== "function" || typeof agentBuilderNamespace.get !== "function") {
|
|
67757
|
-
throw new Error("Server misconfigured: AGENT_BUILDER Durable Object binding is required for platform auth");
|
|
67758
|
-
}
|
|
67759
|
-
const agentBuilderId = agentBuilderNamespace.idFromName("singleton");
|
|
67760
|
-
const agentBuilder = agentBuilderNamespace.get(agentBuilderId);
|
|
68052
|
+
const agentBuilder = agentBuilderAuthStub(env2);
|
|
67761
68053
|
const user = await agentBuilder.upsertPlatformReplicaUser({
|
|
67762
68054
|
platform_user_id: identity.user.id,
|
|
67763
68055
|
username: identity.user.username,
|
|
@@ -67813,7 +68105,7 @@ var index_get_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
67813
68105
|
});
|
|
67814
68106
|
|
|
67815
68107
|
// src/api/api-keys/index.post.ts
|
|
67816
|
-
var
|
|
68108
|
+
var index_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
67817
68109
|
try {
|
|
67818
68110
|
if (isPlatformHosted(env2)) {
|
|
67819
68111
|
return Response.json({ error: "API keys are managed in the Standard Agents platform." }, { status: 410 });
|
|
@@ -68031,7 +68323,7 @@ var config_get_default = defineController2(async ({ config, env: env2, req }) =>
|
|
|
68031
68323
|
});
|
|
68032
68324
|
|
|
68033
68325
|
// src/version.ts
|
|
68034
|
-
var BUILDER_VERSION = "0.38.
|
|
68326
|
+
var BUILDER_VERSION = "0.38.1".length > 0 ? "0.38.1" : "dev";
|
|
68035
68327
|
|
|
68036
68328
|
// src/api/diagnostics.get.ts
|
|
68037
68329
|
init_LLMRequest();
|
|
@@ -68429,11 +68721,6 @@ var models_get_default = defineController2(async ({ models, modelNames }) => {
|
|
|
68429
68721
|
const validModels = modelList.filter(Boolean);
|
|
68430
68722
|
return Response.json({ models: validModels });
|
|
68431
68723
|
});
|
|
68432
|
-
|
|
68433
|
-
// src/api/new-test.get.ts
|
|
68434
|
-
var new_test_get_default = defineController2(async ({ req, params, env: env2 }) => {
|
|
68435
|
-
return { message: "Modified new test API route", timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
68436
|
-
});
|
|
68437
68724
|
function toJSONSchema(schema) {
|
|
68438
68725
|
if (!schema) return null;
|
|
68439
68726
|
if (schema && typeof schema === "object" && ("~standard" in schema || "_def" in schema)) {
|
|
@@ -68540,6 +68827,7 @@ var providers_get_default = defineController2(async ({ env: env2 }) => {
|
|
|
68540
68827
|
});
|
|
68541
68828
|
|
|
68542
68829
|
// src/api/skills/index.get.ts
|
|
68830
|
+
init_scope();
|
|
68543
68831
|
var index_get_default2 = defineController2(async ({ req, env: env2 }) => {
|
|
68544
68832
|
const authResult = await requireAdmin(req, env2);
|
|
68545
68833
|
if (authResult instanceof Response) return authResult;
|
|
@@ -68547,7 +68835,10 @@ var index_get_default2 = defineController2(async ({ req, env: env2 }) => {
|
|
|
68547
68835
|
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
68548
68836
|
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
68549
68837
|
try {
|
|
68550
|
-
const skills = await agentBuilder.listSkills(
|
|
68838
|
+
const skills = await agentBuilder.listSkills(
|
|
68839
|
+
{ ownerId: SHARED_SKILL_OWNER },
|
|
68840
|
+
{ includeDisabled }
|
|
68841
|
+
);
|
|
68551
68842
|
return Response.json({ skills });
|
|
68552
68843
|
} catch (error) {
|
|
68553
68844
|
return Response.json(
|
|
@@ -68562,7 +68853,8 @@ var SkillValidationError = class extends Error {
|
|
|
68562
68853
|
};
|
|
68563
68854
|
|
|
68564
68855
|
// src/api/skills/index.post.ts
|
|
68565
|
-
|
|
68856
|
+
init_scope();
|
|
68857
|
+
var index_post_default2 = defineController2(async ({ req, env: env2 }) => {
|
|
68566
68858
|
const authResult = await requireAdmin(req, env2);
|
|
68567
68859
|
if (authResult instanceof Response) return authResult;
|
|
68568
68860
|
let body;
|
|
@@ -68584,7 +68876,7 @@ var index_post_default3 = defineController2(async ({ req, env: env2 }) => {
|
|
|
68584
68876
|
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
68585
68877
|
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
68586
68878
|
try {
|
|
68587
|
-
const skill = await agentBuilder.upsertSkill(files);
|
|
68879
|
+
const skill = await agentBuilder.upsertSkill({ ownerId: SHARED_SKILL_OWNER }, files);
|
|
68588
68880
|
return Response.json({ skill }, { status: 201 });
|
|
68589
68881
|
} catch (error) {
|
|
68590
68882
|
const message = error instanceof Error ? error.message : "Failed to install skill";
|
|
@@ -68646,7 +68938,7 @@ async function hasEnabledImmediatePromptTools(agentBuilder, threadId, agentId) {
|
|
|
68646
68938
|
}
|
|
68647
68939
|
return false;
|
|
68648
68940
|
}
|
|
68649
|
-
var
|
|
68941
|
+
var index_post_default3 = defineController2(async ({ req, env: env2 }) => {
|
|
68650
68942
|
const authResult = await requireAuth(req, env2);
|
|
68651
68943
|
if (authResult instanceof Response) {
|
|
68652
68944
|
return authResult;
|
|
@@ -69243,15 +69535,138 @@ var migration17 = {
|
|
|
69243
69535
|
}
|
|
69244
69536
|
};
|
|
69245
69537
|
|
|
69538
|
+
// src/durable-objects/agentbuilder-migrations/0018_auth_security.ts
|
|
69539
|
+
var migration18 = {
|
|
69540
|
+
version: 18,
|
|
69541
|
+
async up(sql) {
|
|
69542
|
+
sql.exec(`
|
|
69543
|
+
CREATE TABLE IF NOT EXISTS super_admin_sessions (
|
|
69544
|
+
token_hash TEXT PRIMARY KEY,
|
|
69545
|
+
created_at INTEGER NOT NULL,
|
|
69546
|
+
expires_at INTEGER NOT NULL
|
|
69547
|
+
)
|
|
69548
|
+
`);
|
|
69549
|
+
sql.exec(`
|
|
69550
|
+
CREATE INDEX IF NOT EXISTS idx_super_admin_sessions_expires
|
|
69551
|
+
ON super_admin_sessions(expires_at)
|
|
69552
|
+
`);
|
|
69553
|
+
sql.exec(`
|
|
69554
|
+
CREATE TABLE IF NOT EXISTS auth_rate_limits (
|
|
69555
|
+
bucket_key TEXT PRIMARY KEY,
|
|
69556
|
+
attempts INTEGER NOT NULL,
|
|
69557
|
+
reset_at INTEGER NOT NULL
|
|
69558
|
+
)
|
|
69559
|
+
`);
|
|
69560
|
+
sql.exec(`
|
|
69561
|
+
CREATE INDEX IF NOT EXISTS idx_auth_rate_limits_reset
|
|
69562
|
+
ON auth_rate_limits(reset_at)
|
|
69563
|
+
`);
|
|
69564
|
+
sql.exec(`
|
|
69565
|
+
INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '18')
|
|
69566
|
+
`);
|
|
69567
|
+
}
|
|
69568
|
+
};
|
|
69569
|
+
|
|
69570
|
+
// src/durable-objects/agentbuilder-migrations/0019_scope_skills.ts
|
|
69571
|
+
var migration19 = {
|
|
69572
|
+
version: 19,
|
|
69573
|
+
async up(sql) {
|
|
69574
|
+
sql.exec(`
|
|
69575
|
+
CREATE TABLE skills_0019 (
|
|
69576
|
+
owner_id TEXT NOT NULL,
|
|
69577
|
+
name TEXT NOT NULL,
|
|
69578
|
+
description TEXT NOT NULL,
|
|
69579
|
+
version TEXT,
|
|
69580
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
69581
|
+
shared INTEGER NOT NULL DEFAULT 0,
|
|
69582
|
+
created_at INTEGER DEFAULT (strftime('%s', 'now')),
|
|
69583
|
+
updated_at INTEGER DEFAULT (strftime('%s', 'now')),
|
|
69584
|
+
PRIMARY KEY (owner_id, name)
|
|
69585
|
+
)
|
|
69586
|
+
`);
|
|
69587
|
+
sql.exec(`
|
|
69588
|
+
INSERT INTO skills_0019 (
|
|
69589
|
+
owner_id, name, description, version, enabled, shared, created_at, updated_at
|
|
69590
|
+
)
|
|
69591
|
+
SELECT '__instance_shared__', name, description, version, enabled, 1, created_at, updated_at
|
|
69592
|
+
FROM skills
|
|
69593
|
+
`);
|
|
69594
|
+
sql.exec(`
|
|
69595
|
+
CREATE TABLE skill_files_0019 (
|
|
69596
|
+
owner_id TEXT NOT NULL,
|
|
69597
|
+
skill_name TEXT NOT NULL,
|
|
69598
|
+
path TEXT NOT NULL,
|
|
69599
|
+
content TEXT NOT NULL,
|
|
69600
|
+
size INTEGER NOT NULL,
|
|
69601
|
+
PRIMARY KEY (owner_id, skill_name, path),
|
|
69602
|
+
FOREIGN KEY (owner_id, skill_name) REFERENCES skills_0019(owner_id, name) ON DELETE CASCADE
|
|
69603
|
+
)
|
|
69604
|
+
`);
|
|
69605
|
+
sql.exec(`
|
|
69606
|
+
INSERT INTO skill_files_0019 (owner_id, skill_name, path, content, size)
|
|
69607
|
+
SELECT '__instance_shared__', skill_name, path, content, size FROM skill_files
|
|
69608
|
+
`);
|
|
69609
|
+
sql.exec(`DROP TABLE skill_files`);
|
|
69610
|
+
sql.exec(`DROP TABLE skills`);
|
|
69611
|
+
sql.exec(`ALTER TABLE skills_0019 RENAME TO skills`);
|
|
69612
|
+
sql.exec(`ALTER TABLE skill_files_0019 RENAME TO skill_files`);
|
|
69613
|
+
sql.exec(`CREATE INDEX idx_skills_owner_enabled ON skills(owner_id, enabled)`);
|
|
69614
|
+
sql.exec(`CREATE INDEX idx_skills_shared_enabled ON skills(shared, enabled)`);
|
|
69615
|
+
sql.exec(`CREATE INDEX idx_skill_files_skill ON skill_files(owner_id, skill_name)`);
|
|
69616
|
+
sql.exec(`INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '19')`);
|
|
69617
|
+
}
|
|
69618
|
+
};
|
|
69619
|
+
|
|
69620
|
+
// src/durable-objects/agentbuilder-migrations/0020_websocket_tickets.ts
|
|
69621
|
+
var migration20 = {
|
|
69622
|
+
version: 20,
|
|
69623
|
+
async up(sql) {
|
|
69624
|
+
sql.exec(`
|
|
69625
|
+
CREATE TABLE websocket_tickets (
|
|
69626
|
+
ticket_hash TEXT PRIMARY KEY,
|
|
69627
|
+
pathname TEXT NOT NULL,
|
|
69628
|
+
auth_json TEXT NOT NULL,
|
|
69629
|
+
created_at INTEGER NOT NULL,
|
|
69630
|
+
expires_at INTEGER NOT NULL
|
|
69631
|
+
)
|
|
69632
|
+
`);
|
|
69633
|
+
sql.exec(`
|
|
69634
|
+
CREATE INDEX idx_websocket_tickets_expires
|
|
69635
|
+
ON websocket_tickets(expires_at)
|
|
69636
|
+
`);
|
|
69637
|
+
sql.exec(`INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '20')`);
|
|
69638
|
+
}
|
|
69639
|
+
};
|
|
69640
|
+
|
|
69641
|
+
// src/durable-objects/agentbuilder-migrations/0021_platform_handoff_jtis.ts
|
|
69642
|
+
var migration21 = {
|
|
69643
|
+
version: 21,
|
|
69644
|
+
async up(sql) {
|
|
69645
|
+
sql.exec(`
|
|
69646
|
+
CREATE TABLE platform_handoff_jtis (
|
|
69647
|
+
jti TEXT PRIMARY KEY,
|
|
69648
|
+
consumed_at INTEGER NOT NULL,
|
|
69649
|
+
expires_at INTEGER NOT NULL
|
|
69650
|
+
)
|
|
69651
|
+
`);
|
|
69652
|
+
sql.exec(`
|
|
69653
|
+
CREATE INDEX idx_platform_handoff_jtis_expires
|
|
69654
|
+
ON platform_handoff_jtis(expires_at)
|
|
69655
|
+
`);
|
|
69656
|
+
sql.exec(`INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '21')`);
|
|
69657
|
+
}
|
|
69658
|
+
};
|
|
69659
|
+
|
|
69246
69660
|
// src/durable-objects/agentbuilder-migrations/index.ts
|
|
69247
|
-
var migrations = [migration, migration2, migration3, migration4, migration5, migration6, migration7, migration8, migration9, migration10, migration11, migration12, migration13, migration14, migration15, migration16, migration17];
|
|
69661
|
+
var migrations = [migration, migration2, migration3, migration4, migration5, migration6, migration7, migration8, migration9, migration10, migration11, migration12, migration13, migration14, migration15, migration16, migration17, migration18, migration19, migration20, migration21];
|
|
69248
69662
|
migrations.reduce(
|
|
69249
|
-
(max,
|
|
69663
|
+
(max, migration22) => Math.max(max, migration22.version),
|
|
69250
69664
|
0
|
|
69251
69665
|
);
|
|
69252
69666
|
|
|
69253
69667
|
// src/durable-objects/DurableAgentBuilder.ts
|
|
69254
69668
|
init_types();
|
|
69669
|
+
init_scope();
|
|
69255
69670
|
var THREAD_PREVIEW_MAX_CHARS = 140;
|
|
69256
69671
|
var buildThreadPreview = (content) => {
|
|
69257
69672
|
const collapsed = content.replace(/\s+/g, " ").trim();
|
|
@@ -69607,7 +70022,7 @@ var index_get_default3 = defineController2(async ({ req, env: env2 }) => {
|
|
|
69607
70022
|
|
|
69608
70023
|
// src/api/users/index.post.ts
|
|
69609
70024
|
var VALID_ROLES = ["admin", "user"];
|
|
69610
|
-
var
|
|
70025
|
+
var index_post_default4 = defineController2(async ({ req, env: env2 }) => {
|
|
69611
70026
|
try {
|
|
69612
70027
|
if (isPlatformHosted(env2)) {
|
|
69613
70028
|
return Response.json({ error: "Users are managed in the Standard Agents platform." }, { status: 410 });
|
|
@@ -69871,7 +70286,7 @@ var name_get_default2 = defineController2(async ({ params, models }) => {
|
|
|
69871
70286
|
});
|
|
69872
70287
|
|
|
69873
70288
|
// src/api/pack/[agentName]/index.post.ts
|
|
69874
|
-
var
|
|
70289
|
+
var index_post_default5 = defineController2(async ({ req, env: env2 }) => {
|
|
69875
70290
|
const auth = await requireAdmin(req, env2);
|
|
69876
70291
|
if (auth instanceof Response) return auth;
|
|
69877
70292
|
const url = new URL(req.url);
|
|
@@ -70051,6 +70466,7 @@ var name_get_default3 = defineController2(async ({ params, prompts, models, mode
|
|
|
70051
70466
|
});
|
|
70052
70467
|
|
|
70053
70468
|
// src/api/skills/[name].delete.ts
|
|
70469
|
+
init_scope();
|
|
70054
70470
|
var name_delete_default = defineController2(async ({ req, env: env2, params }) => {
|
|
70055
70471
|
const authResult = await requireAdmin(req, env2);
|
|
70056
70472
|
if (authResult instanceof Response) return authResult;
|
|
@@ -70059,7 +70475,7 @@ var name_delete_default = defineController2(async ({ req, env: env2, params }) =
|
|
|
70059
70475
|
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
70060
70476
|
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
70061
70477
|
try {
|
|
70062
|
-
const found = await agentBuilder.deleteSkill(name15);
|
|
70478
|
+
const found = await agentBuilder.deleteSkill({ ownerId: SHARED_SKILL_OWNER }, name15);
|
|
70063
70479
|
if (!found) return Response.json({ error: `Skill not found: ${name15}` }, { status: 404 });
|
|
70064
70480
|
return Response.json({ ok: true, removed: name15 });
|
|
70065
70481
|
} catch (error) {
|
|
@@ -70071,6 +70487,7 @@ var name_delete_default = defineController2(async ({ req, env: env2, params }) =
|
|
|
70071
70487
|
});
|
|
70072
70488
|
|
|
70073
70489
|
// src/api/skills/[name].get.ts
|
|
70490
|
+
init_scope();
|
|
70074
70491
|
var name_get_default4 = defineController2(async ({ req, env: env2, params }) => {
|
|
70075
70492
|
const authResult = await requireAdmin(req, env2);
|
|
70076
70493
|
if (authResult instanceof Response) return authResult;
|
|
@@ -70079,9 +70496,10 @@ var name_get_default4 = defineController2(async ({ req, env: env2, params }) =>
|
|
|
70079
70496
|
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
70080
70497
|
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
70081
70498
|
try {
|
|
70082
|
-
const
|
|
70499
|
+
const scope = { ownerId: SHARED_SKILL_OWNER };
|
|
70500
|
+
const skill = await agentBuilder.getSkill(scope, name15);
|
|
70083
70501
|
if (!skill) return Response.json({ error: `Skill not found: ${name15}` }, { status: 404 });
|
|
70084
|
-
const skillMd = await agentBuilder.getSkillFile(name15, "SKILL.md") ?? "";
|
|
70502
|
+
const skillMd = await agentBuilder.getSkillFile(scope, name15, "SKILL.md") ?? "";
|
|
70085
70503
|
return Response.json({ skill, skillMd });
|
|
70086
70504
|
} catch (error) {
|
|
70087
70505
|
return Response.json(
|
|
@@ -70092,6 +70510,7 @@ var name_get_default4 = defineController2(async ({ req, env: env2, params }) =>
|
|
|
70092
70510
|
});
|
|
70093
70511
|
|
|
70094
70512
|
// src/api/skills/[name].patch.ts
|
|
70513
|
+
init_scope();
|
|
70095
70514
|
var name_patch_default = defineController2(async ({ req, env: env2, params }) => {
|
|
70096
70515
|
const authResult = await requireAdmin(req, env2);
|
|
70097
70516
|
if (authResult instanceof Response) return authResult;
|
|
@@ -70109,9 +70528,10 @@ var name_patch_default = defineController2(async ({ req, env: env2, params }) =>
|
|
|
70109
70528
|
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
70110
70529
|
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
70111
70530
|
try {
|
|
70112
|
-
const
|
|
70531
|
+
const scope = { ownerId: SHARED_SKILL_OWNER };
|
|
70532
|
+
const found = await agentBuilder.setSkillEnabled(scope, name15, body.enabled);
|
|
70113
70533
|
if (!found) return Response.json({ error: `Skill not found: ${name15}` }, { status: 404 });
|
|
70114
|
-
const skill = await agentBuilder.getSkill(name15);
|
|
70534
|
+
const skill = await agentBuilder.getSkill(scope, name15);
|
|
70115
70535
|
return Response.json({ skill });
|
|
70116
70536
|
} catch (error) {
|
|
70117
70537
|
return Response.json(
|
|
@@ -70408,7 +70828,6 @@ var id_patch_default = defineController2(async ({ req, env: env2, params }) => {
|
|
|
70408
70828
|
// Map agent_name back to agent_id for API compat
|
|
70409
70829
|
user_id: updatedThread.user_id,
|
|
70410
70830
|
tags: updatedThread.tags || [],
|
|
70411
|
-
env: updatedThread.env ?? updatedThread.tenvs ?? null,
|
|
70412
70831
|
env_types: updatedThread.env_types ?? null,
|
|
70413
70832
|
created_at: updatedThread.created_at
|
|
70414
70833
|
});
|
|
@@ -70424,15 +70843,17 @@ var id_patch_default = defineController2(async ({ req, env: env2, params }) => {
|
|
|
70424
70843
|
// src/middleware/request-auth.ts
|
|
70425
70844
|
async function resolveRequestAuth(context) {
|
|
70426
70845
|
if (context.auth) return context.auth;
|
|
70846
|
+
if (!isAuthenticationEnv(context.env)) {
|
|
70847
|
+
return new Response(JSON.stringify({ error: "Unauthorized" }), {
|
|
70848
|
+
status: 401,
|
|
70849
|
+
headers: { "Content-Type": "application/json" }
|
|
70850
|
+
});
|
|
70851
|
+
}
|
|
70427
70852
|
return requireAuth(context.req, context.env);
|
|
70428
70853
|
}
|
|
70429
|
-
async function resolveOptionalRequestAuth(context) {
|
|
70430
|
-
if (context.auth) return context.auth;
|
|
70431
|
-
return authenticate(context.req, context.env);
|
|
70432
|
-
}
|
|
70433
70854
|
async function resolveRequestPermission(context, permission) {
|
|
70434
70855
|
if (context.auth) {
|
|
70435
|
-
if (!
|
|
70856
|
+
if (!hasPermissionInEnvironment(context.auth.user, permission, context.env)) {
|
|
70436
70857
|
return Response.json(
|
|
70437
70858
|
{ error: `Forbidden: '${permission}' access required` },
|
|
70438
70859
|
{ status: 403 }
|
|
@@ -70578,7 +70999,7 @@ var name_get_default5 = defineController2(async ({ params, tools }) => {
|
|
|
70578
70999
|
|
|
70579
71000
|
// src/api/unpack/[packageId]/index.post.ts
|
|
70580
71001
|
init_package_identifier();
|
|
70581
|
-
var
|
|
71002
|
+
var index_post_default6 = defineController2(async ({ req, env: env2 }) => {
|
|
70582
71003
|
const auth = await requireAdmin(req, env2);
|
|
70583
71004
|
if (auth instanceof Response) return auth;
|
|
70584
71005
|
const url = new URL(req.url);
|
|
@@ -70723,17 +71144,43 @@ var id_put_default = defineController2(async ({ req, env: env2, params }) => {
|
|
|
70723
71144
|
});
|
|
70724
71145
|
|
|
70725
71146
|
// src/api/auth/bootstrap.post.ts
|
|
71147
|
+
var SESSION_TTL_SECONDS2 = 30 * 24 * 60 * 60;
|
|
70726
71148
|
var bootstrap_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
70727
71149
|
try {
|
|
71150
|
+
if (!isTrustedLocalDevelopmentRequest(req, env2) || !isSameOriginBrowserRequest(req)) {
|
|
71151
|
+
return Response.json(
|
|
71152
|
+
{ error: "Local bootstrap is available only to same-origin clients" },
|
|
71153
|
+
{ status: 403, headers: { "Cache-Control": "no-store" } }
|
|
71154
|
+
);
|
|
71155
|
+
}
|
|
70728
71156
|
const platformTokenSession = await createPlatformLocalSession(req, env2);
|
|
70729
71157
|
if (!platformTokenSession) {
|
|
70730
|
-
return new Response(null, {
|
|
71158
|
+
return new Response(null, {
|
|
71159
|
+
status: 204,
|
|
71160
|
+
headers: { "Cache-Control": "no-store" }
|
|
71161
|
+
});
|
|
70731
71162
|
}
|
|
70732
|
-
return Response.json(
|
|
71163
|
+
return Response.json({
|
|
71164
|
+
user: platformTokenSession.user,
|
|
71165
|
+
authType: platformTokenSession.authType,
|
|
71166
|
+
platform: platformTokenSession.platform
|
|
71167
|
+
}, {
|
|
71168
|
+
headers: {
|
|
71169
|
+
"Cache-Control": "no-store",
|
|
71170
|
+
"Set-Cookie": buildSessionCookie(
|
|
71171
|
+
req,
|
|
71172
|
+
platformTokenSession.token,
|
|
71173
|
+
SESSION_TTL_SECONDS2
|
|
71174
|
+
)
|
|
71175
|
+
}
|
|
71176
|
+
});
|
|
70733
71177
|
} catch (error) {
|
|
70734
71178
|
const message = error instanceof Error ? error.message : "Failed to bootstrap platform auth";
|
|
70735
71179
|
const status = message.includes("STANDARD_AGENTS_API_KEY") ? 401 : 502;
|
|
70736
|
-
return Response.json(
|
|
71180
|
+
return Response.json(
|
|
71181
|
+
{ error: message },
|
|
71182
|
+
{ status, headers: { "Cache-Control": "no-store" } }
|
|
71183
|
+
);
|
|
70737
71184
|
}
|
|
70738
71185
|
});
|
|
70739
71186
|
|
|
@@ -70862,7 +71309,51 @@ var config_get_default2 = defineController2(async ({ req, env: env2 }) => {
|
|
|
70862
71309
|
};
|
|
70863
71310
|
});
|
|
70864
71311
|
|
|
71312
|
+
// src/api/auth/current-key.delete.ts
|
|
71313
|
+
var current_key_delete_default = defineController2(async ({ req, env: env2 }) => {
|
|
71314
|
+
try {
|
|
71315
|
+
const auth = await authenticate(req, env2);
|
|
71316
|
+
if (!auth) return Response.json({ error: "Unauthorized" }, { status: 401 });
|
|
71317
|
+
if (auth.authType !== "api_key" || !auth.credentialId) {
|
|
71318
|
+
return Response.json({ error: "An API key must authenticate this request." }, { status: 403 });
|
|
71319
|
+
}
|
|
71320
|
+
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
71321
|
+
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
71322
|
+
await agentBuilder.deleteApiKey(auth.credentialId, auth.user.id);
|
|
71323
|
+
return Response.json({ revoked: true });
|
|
71324
|
+
} catch (error) {
|
|
71325
|
+
console.error("Current API key revocation error:", error);
|
|
71326
|
+
return Response.json(
|
|
71327
|
+
{ error: error instanceof Error ? error.message : "Failed to revoke API key" },
|
|
71328
|
+
{ status: 500 }
|
|
71329
|
+
);
|
|
71330
|
+
}
|
|
71331
|
+
});
|
|
71332
|
+
|
|
71333
|
+
// src/utils/auth-rate-limit.ts
|
|
71334
|
+
function authClientAddress(request) {
|
|
71335
|
+
return request.headers.get("CF-Connecting-IP")?.trim() || request.headers.get("X-Real-IP")?.trim() || request.headers.get("X-Forwarded-For")?.split(",")[0]?.trim() || "unknown";
|
|
71336
|
+
}
|
|
71337
|
+
async function authRateLimitKey(scope, identifier) {
|
|
71338
|
+
return `${scope}:${await hashToken(identifier.trim().toLowerCase())}`;
|
|
71339
|
+
}
|
|
71340
|
+
function authRateLimitedResponse(result) {
|
|
71341
|
+
return Response.json(
|
|
71342
|
+
{ error: "Too many authentication attempts. Try again later." },
|
|
71343
|
+
{
|
|
71344
|
+
status: 429,
|
|
71345
|
+
headers: {
|
|
71346
|
+
"Cache-Control": "no-store",
|
|
71347
|
+
"Retry-After": String(Math.max(1, Math.ceil(result.retry_after)))
|
|
71348
|
+
}
|
|
71349
|
+
}
|
|
71350
|
+
);
|
|
71351
|
+
}
|
|
71352
|
+
|
|
70865
71353
|
// src/api/auth/login.post.ts
|
|
71354
|
+
var LOGIN_ADDRESS_LIMIT = { limit: 10, window_seconds: 5 * 60 };
|
|
71355
|
+
var LOGIN_IDENTITY_LIMIT = { limit: 25, window_seconds: 15 * 60 };
|
|
71356
|
+
var LOGIN_INSTANCE_LIMIT = { limit: 500, window_seconds: 5 * 60 };
|
|
70866
71357
|
var login_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
70867
71358
|
try {
|
|
70868
71359
|
if (isPlatformHosted(env2)) {
|
|
@@ -70879,7 +71370,31 @@ var login_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
70879
71370
|
{ status: 400 }
|
|
70880
71371
|
);
|
|
70881
71372
|
}
|
|
70882
|
-
if (env2.
|
|
71373
|
+
if (!env2.AGENT_BUILDER || typeof env2.AGENT_BUILDER.idFromName !== "function") {
|
|
71374
|
+
return Response.json(
|
|
71375
|
+
{ error: "Server misconfigured: AGENT_BUILDER Durable Object binding is required for local login" },
|
|
71376
|
+
{ status: 500 }
|
|
71377
|
+
);
|
|
71378
|
+
}
|
|
71379
|
+
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
71380
|
+
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
71381
|
+
const instanceLimit = await agentBuilder.consumeAuthRateLimit({
|
|
71382
|
+
key: "login-instance",
|
|
71383
|
+
...LOGIN_INSTANCE_LIMIT
|
|
71384
|
+
});
|
|
71385
|
+
if (!instanceLimit.allowed) return authRateLimitedResponse(instanceLimit);
|
|
71386
|
+
const addressLimit = await agentBuilder.consumeAuthRateLimit({
|
|
71387
|
+
key: await authRateLimitKey("login-address", authClientAddress(req)),
|
|
71388
|
+
...LOGIN_ADDRESS_LIMIT
|
|
71389
|
+
});
|
|
71390
|
+
if (!addressLimit.allowed) return authRateLimitedResponse(addressLimit);
|
|
71391
|
+
const identityLimit = await agentBuilder.consumeAuthRateLimit({
|
|
71392
|
+
key: await authRateLimitKey("login-identity", username || "<missing>"),
|
|
71393
|
+
...LOGIN_IDENTITY_LIMIT
|
|
71394
|
+
});
|
|
71395
|
+
if (!identityLimit.allowed) return authRateLimitedResponse(identityLimit);
|
|
71396
|
+
const isSuperAdminPassword = env2.SUPER_ADMIN_PASSWORD && username === "admin" ? await constantTimeEqual(password, env2.SUPER_ADMIN_PASSWORD) : false;
|
|
71397
|
+
if (isSuperAdminPassword) {
|
|
70883
71398
|
if (!env2.ENCRYPTION_KEY) {
|
|
70884
71399
|
return Response.json(
|
|
70885
71400
|
{ error: "Server misconfigured: ENCRYPTION_KEY required for super admin" },
|
|
@@ -70887,6 +71402,12 @@ var login_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
70887
71402
|
);
|
|
70888
71403
|
}
|
|
70889
71404
|
const token2 = await generateSuperAdminToken(env2.ENCRYPTION_KEY);
|
|
71405
|
+
const tokenHash2 = await hashToken(token2);
|
|
71406
|
+
const expiresAt2 = Math.floor(Date.now() / 1e3) + SUPER_ADMIN_TOKEN_TTL_SECONDS;
|
|
71407
|
+
await agentBuilder.createSuperAdminSession({
|
|
71408
|
+
token_hash: tokenHash2,
|
|
71409
|
+
expires_at: expiresAt2
|
|
71410
|
+
});
|
|
70890
71411
|
return Response.json({
|
|
70891
71412
|
token: token2,
|
|
70892
71413
|
user: {
|
|
@@ -70894,6 +71415,11 @@ var login_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
70894
71415
|
username: "admin",
|
|
70895
71416
|
role: "admin"
|
|
70896
71417
|
}
|
|
71418
|
+
}, {
|
|
71419
|
+
headers: {
|
|
71420
|
+
"Cache-Control": "no-store",
|
|
71421
|
+
"Set-Cookie": buildSessionCookie(req, token2, SUPER_ADMIN_TOKEN_TTL_SECONDS)
|
|
71422
|
+
}
|
|
70897
71423
|
});
|
|
70898
71424
|
}
|
|
70899
71425
|
if (!username) {
|
|
@@ -70902,14 +71428,6 @@ var login_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
70902
71428
|
{ status: 400 }
|
|
70903
71429
|
);
|
|
70904
71430
|
}
|
|
70905
|
-
if (!env2.AGENT_BUILDER || typeof env2.AGENT_BUILDER.idFromName !== "function") {
|
|
70906
|
-
return Response.json(
|
|
70907
|
-
{ error: "Server misconfigured: AGENT_BUILDER Durable Object binding is required for local login" },
|
|
70908
|
-
{ status: 500 }
|
|
70909
|
-
);
|
|
70910
|
-
}
|
|
70911
|
-
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
70912
|
-
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
70913
71431
|
const user = await agentBuilder.getUserByUsername(username);
|
|
70914
71432
|
if (!user) {
|
|
70915
71433
|
return Response.json(
|
|
@@ -70939,11 +71457,16 @@ var login_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
70939
71457
|
username: user.username,
|
|
70940
71458
|
role: user.role
|
|
70941
71459
|
}
|
|
71460
|
+
}, {
|
|
71461
|
+
headers: {
|
|
71462
|
+
"Cache-Control": "no-store",
|
|
71463
|
+
"Set-Cookie": buildSessionCookie(req, token, 30 * 24 * 60 * 60)
|
|
71464
|
+
}
|
|
70942
71465
|
});
|
|
70943
71466
|
} catch (error) {
|
|
70944
71467
|
console.error("Login error:", error);
|
|
70945
71468
|
return Response.json(
|
|
70946
|
-
{ error: error.message
|
|
71469
|
+
{ error: error instanceof Error ? error.message : "Login failed" },
|
|
70947
71470
|
{ status: 500 }
|
|
70948
71471
|
);
|
|
70949
71472
|
}
|
|
@@ -70956,38 +71479,23 @@ async function deleteLocalSession(req, env2) {
|
|
|
70956
71479
|
if (!token) {
|
|
70957
71480
|
return;
|
|
70958
71481
|
}
|
|
70959
|
-
|
|
70960
|
-
|
|
70961
|
-
|
|
71482
|
+
const tokenHash = await hashToken(token);
|
|
71483
|
+
const agentBuilder = env2.AGENT_BUILDER.get(env2.AGENT_BUILDER.idFromName("singleton"));
|
|
71484
|
+
if (token.includes(".")) {
|
|
71485
|
+
await agentBuilder.deleteSuperAdminSession(tokenHash);
|
|
71486
|
+
} else if (isValidUserToken(token)) {
|
|
70962
71487
|
await agentBuilder.deleteSession(tokenHash);
|
|
70963
71488
|
}
|
|
70964
71489
|
}
|
|
70965
71490
|
function clearedSessionCookie(req) {
|
|
70966
71491
|
return buildSessionCookie(req, "", 0);
|
|
70967
71492
|
}
|
|
70968
|
-
|
|
70969
|
-
|
|
70970
|
-
|
|
70971
|
-
|
|
70972
|
-
return
|
|
71493
|
+
function isSameOriginLogout(req) {
|
|
71494
|
+
const origin = req.headers.get("Origin");
|
|
71495
|
+
if (origin && origin !== new URL(req.url).origin) return false;
|
|
71496
|
+
const fetchSite = req.headers.get("Sec-Fetch-Site");
|
|
71497
|
+
return !fetchSite || fetchSite === "same-origin" || fetchSite === "none";
|
|
70973
71498
|
}
|
|
70974
|
-
var logout_get_default = defineController2(async ({ req, env: env2 }) => {
|
|
70975
|
-
try {
|
|
70976
|
-
await deleteLocalSession(req, env2);
|
|
70977
|
-
} catch (error) {
|
|
70978
|
-
console.error("Logout error:", error);
|
|
70979
|
-
}
|
|
70980
|
-
const url = new URL(req.url);
|
|
70981
|
-
const returnTo = safeReturnTo(url.searchParams.get("return_to"));
|
|
70982
|
-
const location = isPlatformHosted(env2) ? platformLogoutUrl(req, env2, returnTo) : `${url.origin}/login`;
|
|
70983
|
-
return new Response(null, {
|
|
70984
|
-
status: 302,
|
|
70985
|
-
headers: {
|
|
70986
|
-
Location: location,
|
|
70987
|
-
"Set-Cookie": clearedSessionCookie(req)
|
|
70988
|
-
}
|
|
70989
|
-
});
|
|
70990
|
-
});
|
|
70991
71499
|
|
|
70992
71500
|
// src/api/auth/logout.post.ts
|
|
70993
71501
|
var logout_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
@@ -70998,9 +71506,15 @@ var logout_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
70998
71506
|
"Set-Cookie": clearedSessionCookie(req)
|
|
70999
71507
|
}
|
|
71000
71508
|
});
|
|
71509
|
+
if (!isSameOriginLogout(req)) {
|
|
71510
|
+
return Response.json({ error: "Cross-origin logout refused" }, { status: 403 });
|
|
71511
|
+
}
|
|
71001
71512
|
try {
|
|
71002
71513
|
await deleteLocalSession(req, env2);
|
|
71003
|
-
|
|
71514
|
+
const url = new URL(req.url);
|
|
71515
|
+
const returnTo = url.searchParams.get("return_to");
|
|
71516
|
+
const redirect = isPlatformHosted(env2) ? platformLogoutUrl(req, env2, returnTo) : void 0;
|
|
71517
|
+
return clearCookie({ success: true, ...redirect ? { redirect } : {} });
|
|
71004
71518
|
} catch (error) {
|
|
71005
71519
|
console.error("Logout error:", error);
|
|
71006
71520
|
return clearCookie({ error: error.message || "Logout failed" }, 500);
|
|
@@ -71103,6 +71617,37 @@ var platform_replica_post_default = defineController2(async ({ req, env: env2 })
|
|
|
71103
71617
|
return Response.json({ ok: true, ...result });
|
|
71104
71618
|
});
|
|
71105
71619
|
|
|
71620
|
+
// src/api/auth/websocket-ticket.post.ts
|
|
71621
|
+
var WEBSOCKET_TICKET_TTL_SECONDS = 30;
|
|
71622
|
+
var websocket_ticket_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
71623
|
+
const auth = await authenticate(req, env2);
|
|
71624
|
+
if (!auth) return Response.json({ error: "Unauthorized" }, { status: 401 });
|
|
71625
|
+
let body;
|
|
71626
|
+
try {
|
|
71627
|
+
body = await req.json();
|
|
71628
|
+
} catch {
|
|
71629
|
+
return Response.json({ error: "A JSON body is required." }, { status: 400 });
|
|
71630
|
+
}
|
|
71631
|
+
const pathname = body && typeof body === "object" ? body.pathname : void 0;
|
|
71632
|
+
if (typeof pathname !== "string" || !isWebSocketTicketPath(pathname)) {
|
|
71633
|
+
return Response.json({ error: "pathname must be a normalized /api/* path." }, { status: 400 });
|
|
71634
|
+
}
|
|
71635
|
+
const ticket = generateSecureToken(32);
|
|
71636
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
71637
|
+
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
71638
|
+
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
71639
|
+
await agentBuilder.createWebSocketTicket({
|
|
71640
|
+
ticket_hash: await hashToken(ticket),
|
|
71641
|
+
pathname,
|
|
71642
|
+
auth_json: JSON.stringify(auth),
|
|
71643
|
+
expires_at: now + WEBSOCKET_TICKET_TTL_SECONDS
|
|
71644
|
+
});
|
|
71645
|
+
return Response.json(
|
|
71646
|
+
{ ticket, expires_in: WEBSOCKET_TICKET_TTL_SECONDS },
|
|
71647
|
+
{ headers: { "Cache-Control": "no-store" } }
|
|
71648
|
+
);
|
|
71649
|
+
});
|
|
71650
|
+
|
|
71106
71651
|
// src/api/envs/_shared.ts
|
|
71107
71652
|
function buildScopedEnvResponse(entries) {
|
|
71108
71653
|
const variables = [...entries].sort((a, b) => a.name.localeCompare(b.name)).map((entry) => ({
|
|
@@ -71579,6 +72124,7 @@ var path_default = defineController2(async ({ req, params, env: env2, url }) =>
|
|
|
71579
72124
|
});
|
|
71580
72125
|
|
|
71581
72126
|
// src/api/platform-auth/bootstrap.post.ts
|
|
72127
|
+
var AGENT_BUILDER_SESSION_TTL_SECONDS = 30 * 24 * 60 * 60;
|
|
71582
72128
|
function uniqueEndpoints(preferred, candidates) {
|
|
71583
72129
|
return Array.from(new Set([preferred, ...candidates].filter((value) => Boolean(value))));
|
|
71584
72130
|
}
|
|
@@ -71593,10 +72139,10 @@ function buildSessionCookieHeader(req, sessionCookie) {
|
|
|
71593
72139
|
return `${sessionCookie}; ${attributes.join("; ")}`;
|
|
71594
72140
|
}
|
|
71595
72141
|
var bootstrap_post_default2 = defineController2(async ({ req, env: env2 }) => {
|
|
71596
|
-
if (!isTrustedLocalDevelopmentRequest(req, env2)) {
|
|
72142
|
+
if (!isTrustedLocalDevelopmentRequest(req, env2) || !isSameOriginBrowserRequest(req)) {
|
|
71597
72143
|
return Response.json(
|
|
71598
|
-
{ error: "Platform auth bridge is
|
|
71599
|
-
{ status:
|
|
72144
|
+
{ error: "Platform auth bridge is restricted to same-origin local development" },
|
|
72145
|
+
{ status: 403 }
|
|
71600
72146
|
);
|
|
71601
72147
|
}
|
|
71602
72148
|
const requestCookie = req.headers.get("Cookie")?.trim() || "";
|
|
@@ -71623,10 +72169,16 @@ var bootstrap_post_default2 = defineController2(async ({ req, env: env2 }) => {
|
|
|
71623
72169
|
account: localSession.platform.account,
|
|
71624
72170
|
authType: localSession.authType,
|
|
71625
72171
|
verified: localSession.platform.verified,
|
|
71626
|
-
token: localSession.token,
|
|
71627
72172
|
localUser: localSession.user
|
|
71628
72173
|
}, {
|
|
71629
|
-
headers: {
|
|
72174
|
+
headers: {
|
|
72175
|
+
"Cache-Control": "no-store",
|
|
72176
|
+
"Set-Cookie": buildSessionCookie(
|
|
72177
|
+
req,
|
|
72178
|
+
localSession.token,
|
|
72179
|
+
AGENT_BUILDER_SESSION_TTL_SECONDS
|
|
72180
|
+
)
|
|
72181
|
+
}
|
|
71630
72182
|
});
|
|
71631
72183
|
}
|
|
71632
72184
|
}
|
|
@@ -73281,11 +73833,9 @@ var tools_get_default2 = defineController2(async ({ params, url }) => {
|
|
|
73281
73833
|
|
|
73282
73834
|
// src/api/threads/[id]/bridge.ts
|
|
73283
73835
|
var bridge_default = defineController2(async ({ req, params, env: env2 }) => {
|
|
73284
|
-
|
|
73285
|
-
|
|
73286
|
-
|
|
73287
|
-
return authResult;
|
|
73288
|
-
}
|
|
73836
|
+
const authResult = await requireAuth(req, env2);
|
|
73837
|
+
if (authResult instanceof Response) {
|
|
73838
|
+
return authResult;
|
|
73289
73839
|
}
|
|
73290
73840
|
const threadId = params.id;
|
|
73291
73841
|
if (!threadId) {
|
|
@@ -73538,19 +74088,9 @@ var cost_get_default = defineController2(async ({ req, params, env: env2 }) => {
|
|
|
73538
74088
|
|
|
73539
74089
|
// src/api/threads/[id]/diagnostics.get.ts
|
|
73540
74090
|
var diagnostics_get_default2 = defineController2(async ({ req, params, env: env2 }) => {
|
|
73541
|
-
|
|
73542
|
-
|
|
73543
|
-
|
|
73544
|
-
return authResult;
|
|
73545
|
-
}
|
|
73546
|
-
} else {
|
|
73547
|
-
const authContext = await authenticate(req, env2);
|
|
73548
|
-
if (authContext && !hasPermission(authContext.user, "logs")) {
|
|
73549
|
-
return Response.json(
|
|
73550
|
-
{ error: "Forbidden: 'logs' access required" },
|
|
73551
|
-
{ status: 403 }
|
|
73552
|
-
);
|
|
73553
|
-
}
|
|
74091
|
+
const authResult = await requirePermission(req, env2, "logs");
|
|
74092
|
+
if (authResult instanceof Response) {
|
|
74093
|
+
return authResult;
|
|
73554
74094
|
}
|
|
73555
74095
|
const threadId = params.id;
|
|
73556
74096
|
if (!threadId) {
|
|
@@ -73718,6 +74258,33 @@ var fs_default = defineController2(async ({ req, params, env: env2 }) => {
|
|
|
73718
74258
|
}
|
|
73719
74259
|
});
|
|
73720
74260
|
|
|
74261
|
+
// src/utils/kv-key-policy.ts
|
|
74262
|
+
var THREAD_CLIENT_RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
74263
|
+
"execution_owner",
|
|
74264
|
+
"approvals",
|
|
74265
|
+
"bg_processes",
|
|
74266
|
+
"lines_capacity_cache"
|
|
74267
|
+
]);
|
|
74268
|
+
var THREAD_CLIENT_RESERVED_PREFIXES = [
|
|
74269
|
+
"approval_"
|
|
74270
|
+
];
|
|
74271
|
+
var USER_CLIENT_RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
74272
|
+
"standardcode.lines.leases",
|
|
74273
|
+
"standardcode.lines.capacity_cache"
|
|
74274
|
+
]);
|
|
74275
|
+
function isThreadKvKeyClientWritable(key) {
|
|
74276
|
+
return !THREAD_CLIENT_RESERVED_KEYS.has(key) && !THREAD_CLIENT_RESERVED_PREFIXES.some((prefix) => key.startsWith(prefix));
|
|
74277
|
+
}
|
|
74278
|
+
function isUserKvKeyClientWritable(key) {
|
|
74279
|
+
return !USER_CLIENT_RESERVED_KEYS.has(key);
|
|
74280
|
+
}
|
|
74281
|
+
function reservedKvKeyResponse() {
|
|
74282
|
+
return Response.json(
|
|
74283
|
+
{ error: "Key is reserved for server-managed state" },
|
|
74284
|
+
{ status: 403 }
|
|
74285
|
+
);
|
|
74286
|
+
}
|
|
74287
|
+
|
|
73721
74288
|
// src/api/threads/[id]/kv/index.ts
|
|
73722
74289
|
async function getAuthorizedThreadStub2(context, threadId) {
|
|
73723
74290
|
const { env: env2 } = context;
|
|
@@ -73811,11 +74378,14 @@ async function handlePost(stub, req) {
|
|
|
73811
74378
|
if (body instanceof Response) return body;
|
|
73812
74379
|
const key = readKey(body.key);
|
|
73813
74380
|
if (key instanceof Response) return key;
|
|
74381
|
+
const previousKey = typeof body.previousKey === "string" && body.previousKey !== key ? body.previousKey : null;
|
|
74382
|
+
if (!isThreadKvKeyClientWritable(key) || previousKey?.trim() && !isThreadKvKeyClientWritable(previousKey)) {
|
|
74383
|
+
return reservedKvKeyResponse();
|
|
74384
|
+
}
|
|
73814
74385
|
if (!Object.prototype.hasOwnProperty.call(body, "value")) {
|
|
73815
74386
|
return Response.json({ error: "Value is required" }, { status: 400 });
|
|
73816
74387
|
}
|
|
73817
74388
|
await stub.setValue(key, body.value);
|
|
73818
|
-
const previousKey = typeof body.previousKey === "string" && body.previousKey !== key ? body.previousKey : null;
|
|
73819
74389
|
if (previousKey?.trim()) {
|
|
73820
74390
|
await stub.setValue(previousKey, null);
|
|
73821
74391
|
}
|
|
@@ -73841,6 +74411,7 @@ async function handleDelete(stub, req, url) {
|
|
|
73841
74411
|
}
|
|
73842
74412
|
const key = readKey(keyValue);
|
|
73843
74413
|
if (key instanceof Response) return key;
|
|
74414
|
+
if (!isThreadKvKeyClientWritable(key)) return reservedKvKeyResponse();
|
|
73844
74415
|
await stub.setValue(key, null);
|
|
73845
74416
|
return new Response(null, { status: 204 });
|
|
73846
74417
|
}
|
|
@@ -73878,19 +74449,9 @@ var kv_default = defineController2(async (context) => {
|
|
|
73878
74449
|
// src/api/threads/[id]/logs.get.ts
|
|
73879
74450
|
var logs_get_default = defineController2(async (context) => {
|
|
73880
74451
|
const { req, params, env: env2 } = context;
|
|
73881
|
-
|
|
73882
|
-
|
|
73883
|
-
|
|
73884
|
-
return authResult;
|
|
73885
|
-
}
|
|
73886
|
-
} else {
|
|
73887
|
-
const authContext = await resolveOptionalRequestAuth(context);
|
|
73888
|
-
if (authContext && !hasPermission(authContext.user, "logs")) {
|
|
73889
|
-
return Response.json(
|
|
73890
|
-
{ error: "Forbidden: 'logs' access required" },
|
|
73891
|
-
{ status: 403 }
|
|
73892
|
-
);
|
|
73893
|
-
}
|
|
74452
|
+
const authResult = await resolveRequestPermission(context, "logs");
|
|
74453
|
+
if (authResult instanceof Response) {
|
|
74454
|
+
return authResult;
|
|
73894
74455
|
}
|
|
73895
74456
|
const url = new URL(req.url);
|
|
73896
74457
|
const threadId = params.id;
|
|
@@ -74123,19 +74684,9 @@ var pending_tool_calls_get_default = defineController2(async ({ params, env: env
|
|
|
74123
74684
|
|
|
74124
74685
|
// src/api/threads/[id]/revive.post.ts
|
|
74125
74686
|
var revive_post_default = defineController2(async ({ req, params, env: env2 }) => {
|
|
74126
|
-
|
|
74127
|
-
|
|
74128
|
-
|
|
74129
|
-
return authResult;
|
|
74130
|
-
}
|
|
74131
|
-
} else {
|
|
74132
|
-
const authContext = await authenticate(req, env2);
|
|
74133
|
-
if (authContext && !hasPermission(authContext.user, "logs")) {
|
|
74134
|
-
return Response.json(
|
|
74135
|
-
{ error: "Forbidden: 'logs' access required" },
|
|
74136
|
-
{ status: 403 }
|
|
74137
|
-
);
|
|
74138
|
-
}
|
|
74687
|
+
const authResult = await requirePermission(req, env2, "logs");
|
|
74688
|
+
if (authResult instanceof Response) {
|
|
74689
|
+
return authResult;
|
|
74139
74690
|
}
|
|
74140
74691
|
const threadId = params.id;
|
|
74141
74692
|
if (!threadId) {
|
|
@@ -74169,20 +74720,15 @@ var revive_post_default = defineController2(async ({ req, params, env: env2 }) =
|
|
|
74169
74720
|
});
|
|
74170
74721
|
|
|
74171
74722
|
// src/api/threads/[id]/rpc.post.ts
|
|
74723
|
+
function unsafeLocalRpcEnabled(env2) {
|
|
74724
|
+
const value = Reflect.get(env2, "AGENT_BUILDER_ENABLE_UNSAFE_RPC");
|
|
74725
|
+
if (typeof value !== "string") return value === true;
|
|
74726
|
+
const normalized = value.trim().toLowerCase();
|
|
74727
|
+
return normalized === "1" || normalized === "true";
|
|
74728
|
+
}
|
|
74172
74729
|
var rpc_post_default = defineController2(async ({ req, params, env: env2 }) => {
|
|
74173
|
-
if (
|
|
74174
|
-
|
|
74175
|
-
if (authResult instanceof Response) {
|
|
74176
|
-
return authResult;
|
|
74177
|
-
}
|
|
74178
|
-
} else {
|
|
74179
|
-
const authContext = await authenticate(req, env2);
|
|
74180
|
-
if (authContext && !hasPermission(authContext.user, "logs")) {
|
|
74181
|
-
return Response.json(
|
|
74182
|
-
{ error: "Forbidden: 'logs' access required" },
|
|
74183
|
-
{ status: 403 }
|
|
74184
|
-
);
|
|
74185
|
-
}
|
|
74730
|
+
if (!isTrustedLocalDevelopmentRequest(req, env2) || !unsafeLocalRpcEnabled(env2)) {
|
|
74731
|
+
return Response.json({ error: "Not found" }, { status: 404 });
|
|
74186
74732
|
}
|
|
74187
74733
|
const threadId = params.id;
|
|
74188
74734
|
if (!threadId) {
|
|
@@ -74196,7 +74742,11 @@ var rpc_post_default = defineController2(async ({ req, params, env: env2 }) => {
|
|
|
74196
74742
|
try {
|
|
74197
74743
|
const id = env2.AGENT_BUILDER_THREAD.idFromName(threadId);
|
|
74198
74744
|
const thread = env2.AGENT_BUILDER_THREAD.get(id);
|
|
74199
|
-
const
|
|
74745
|
+
const rpcMethod = Reflect.get(thread, method);
|
|
74746
|
+
if (typeof rpcMethod !== "function") {
|
|
74747
|
+
return Response.json({ error: "Method not found" }, { status: 404 });
|
|
74748
|
+
}
|
|
74749
|
+
const result = await Reflect.apply(rpcMethod, thread, args);
|
|
74200
74750
|
if (result instanceof Response) {
|
|
74201
74751
|
return result;
|
|
74202
74752
|
}
|
|
@@ -74240,11 +74790,9 @@ var stop_post_default = defineController2(async ({ params, env: env2 }) => {
|
|
|
74240
74790
|
|
|
74241
74791
|
// src/api/threads/[id]/stream.ts
|
|
74242
74792
|
var stream_default = defineController2(async ({ req, params, env: env2 }) => {
|
|
74243
|
-
|
|
74244
|
-
|
|
74245
|
-
|
|
74246
|
-
return authResult;
|
|
74247
|
-
}
|
|
74793
|
+
const authResult = await requireAuth(req, env2);
|
|
74794
|
+
if (authResult instanceof Response) {
|
|
74795
|
+
return authResult;
|
|
74248
74796
|
}
|
|
74249
74797
|
const threadId = params.id;
|
|
74250
74798
|
if (!threadId) {
|
|
@@ -74321,6 +74869,9 @@ var tool_result_post_default = defineController2(async ({ req, params, env: env2
|
|
|
74321
74869
|
if (!toolCallId || typeof toolCallId !== "string") {
|
|
74322
74870
|
return Response.json({ error: "tool_call_id required" }, { status: 400 });
|
|
74323
74871
|
}
|
|
74872
|
+
if (!body.delivery_token || typeof body.delivery_token !== "string") {
|
|
74873
|
+
return Response.json({ error: "delivery_token required" }, { status: 400 });
|
|
74874
|
+
}
|
|
74324
74875
|
try {
|
|
74325
74876
|
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
74326
74877
|
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
@@ -74336,7 +74887,8 @@ var tool_result_post_default = defineController2(async ({ req, params, env: env2
|
|
|
74336
74887
|
typeof body.result === "string" ? body.result : void 0,
|
|
74337
74888
|
typeof body.error === "string" ? body.error : void 0,
|
|
74338
74889
|
typeof body.client_id === "string" ? body.client_id : void 0,
|
|
74339
|
-
typeof body.generation === "number" ? body.generation : void 0
|
|
74890
|
+
typeof body.generation === "number" ? body.generation : void 0,
|
|
74891
|
+
body.delivery_token
|
|
74340
74892
|
);
|
|
74341
74893
|
if (!delivered) {
|
|
74342
74894
|
return Response.json({ status: "ignored" }, { status: 200 });
|
|
@@ -74647,11 +75199,23 @@ var name_get_default8 = defineController2(async ({ params, url, prompts, agents,
|
|
|
74647
75199
|
});
|
|
74648
75200
|
|
|
74649
75201
|
// src/api/auth/device/start.post.ts
|
|
75202
|
+
var DEVICE_ADDRESS_LIMIT = { limit: 20, window_seconds: 10 * 60 };
|
|
75203
|
+
var DEVICE_INSTANCE_LIMIT = { limit: 300, window_seconds: 10 * 60 };
|
|
74650
75204
|
var start_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
74651
|
-
const bytes = crypto.getRandomValues(new Uint8Array(24));
|
|
74652
|
-
const code = [...bytes].map((b) => "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789"[b % 57]).join("");
|
|
74653
75205
|
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
74654
75206
|
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
75207
|
+
const addressLimit = await agentBuilder.consumeAuthRateLimit({
|
|
75208
|
+
key: await authRateLimitKey("device-start-address", authClientAddress(req)),
|
|
75209
|
+
...DEVICE_ADDRESS_LIMIT
|
|
75210
|
+
});
|
|
75211
|
+
if (!addressLimit.allowed) return authRateLimitedResponse(addressLimit);
|
|
75212
|
+
const instanceLimit = await agentBuilder.consumeAuthRateLimit({
|
|
75213
|
+
key: "device-start-instance",
|
|
75214
|
+
...DEVICE_INSTANCE_LIMIT
|
|
75215
|
+
});
|
|
75216
|
+
if (!instanceLimit.allowed) return authRateLimitedResponse(instanceLimit);
|
|
75217
|
+
const bytes = crypto.getRandomValues(new Uint8Array(24));
|
|
75218
|
+
const code = [...bytes].map((b) => "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789"[b % 57]).join("");
|
|
74655
75219
|
await agentBuilder.startDeviceLogin(await hashToken(code));
|
|
74656
75220
|
const origin = new URL(req.url).origin;
|
|
74657
75221
|
const verifyBaseRaw = env2.STANDARD_AGENTS_DEVICE_VERIFY_URL_BASE;
|
|
@@ -74665,8 +75229,74 @@ var start_post_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
74665
75229
|
});
|
|
74666
75230
|
});
|
|
74667
75231
|
|
|
75232
|
+
// src/api/auth/sa/_login-state.ts
|
|
75233
|
+
var LOGIN_STATE_COOKIE = "agtbldr_sa_login_state";
|
|
75234
|
+
var LOGIN_STATE_PARAM = "__sa_login_state";
|
|
75235
|
+
var LOGIN_STATE_TTL_SECONDS = 10 * 60;
|
|
75236
|
+
function safeReturnTo(value) {
|
|
75237
|
+
if (!value || !value.startsWith("/") || value.startsWith("//")) return "/";
|
|
75238
|
+
return value;
|
|
75239
|
+
}
|
|
75240
|
+
function stateCookie(req, value, maxAge) {
|
|
75241
|
+
const attributes = ["Path=/api/auth/sa", "HttpOnly", "SameSite=Lax"];
|
|
75242
|
+
if (new URL(req.url).protocol === "https:") attributes.push("Secure");
|
|
75243
|
+
return `${LOGIN_STATE_COOKIE}=${encodeURIComponent(value)}; ${attributes.join("; ")}; Max-Age=${maxAge}`;
|
|
75244
|
+
}
|
|
75245
|
+
function readStateCookie(req) {
|
|
75246
|
+
const raw = req.headers.get("Cookie");
|
|
75247
|
+
if (!raw) return null;
|
|
75248
|
+
for (const part of raw.split(";")) {
|
|
75249
|
+
const separator = part.indexOf("=");
|
|
75250
|
+
if (separator < 0 || part.slice(0, separator).trim() !== LOGIN_STATE_COOKIE) continue;
|
|
75251
|
+
try {
|
|
75252
|
+
return decodeURIComponent(part.slice(separator + 1).trim()) || null;
|
|
75253
|
+
} catch {
|
|
75254
|
+
return null;
|
|
75255
|
+
}
|
|
75256
|
+
}
|
|
75257
|
+
return null;
|
|
75258
|
+
}
|
|
75259
|
+
function statefulReturnTo(returnTo, state) {
|
|
75260
|
+
const target = new URL(safeReturnTo(returnTo), "https://instance.invalid");
|
|
75261
|
+
target.searchParams.set(LOGIN_STATE_PARAM, state);
|
|
75262
|
+
return `${target.pathname}${target.search}${target.hash}`;
|
|
75263
|
+
}
|
|
75264
|
+
function beginPlatformLogin(req, env2, returnTo, error) {
|
|
75265
|
+
const state = crypto.randomUUID();
|
|
75266
|
+
const location = new URL(platformLoginUrl(req, env2, statefulReturnTo(returnTo, state)));
|
|
75267
|
+
if (error) location.searchParams.set("error", error);
|
|
75268
|
+
return new Response(null, {
|
|
75269
|
+
status: 302,
|
|
75270
|
+
headers: {
|
|
75271
|
+
Location: location.toString(),
|
|
75272
|
+
"Set-Cookie": stateCookie(req, state, LOGIN_STATE_TTL_SECONDS),
|
|
75273
|
+
"Cache-Control": "no-store"
|
|
75274
|
+
}
|
|
75275
|
+
});
|
|
75276
|
+
}
|
|
75277
|
+
function consumePlatformLoginState(req, rawReturnTo) {
|
|
75278
|
+
const target = new URL(safeReturnTo(rawReturnTo), "https://instance.invalid");
|
|
75279
|
+
const state = target.searchParams.get(LOGIN_STATE_PARAM);
|
|
75280
|
+
target.searchParams.delete(LOGIN_STATE_PARAM);
|
|
75281
|
+
const returnTo = `${target.pathname}${target.search}${target.hash}`;
|
|
75282
|
+
return {
|
|
75283
|
+
returnTo,
|
|
75284
|
+
valid: Boolean(state && state === readStateCookie(req)),
|
|
75285
|
+
present: Boolean(state)
|
|
75286
|
+
};
|
|
75287
|
+
}
|
|
75288
|
+
function withClearedPlatformLoginState(req, response) {
|
|
75289
|
+
const headers = new Headers(response.headers);
|
|
75290
|
+
headers.append("Set-Cookie", stateCookie(req, "", 0));
|
|
75291
|
+
return new Response(response.body, {
|
|
75292
|
+
status: response.status,
|
|
75293
|
+
statusText: response.statusText,
|
|
75294
|
+
headers
|
|
75295
|
+
});
|
|
75296
|
+
}
|
|
75297
|
+
|
|
74668
75298
|
// src/api/auth/sa/callback.get.ts
|
|
74669
|
-
var
|
|
75299
|
+
var SESSION_TTL_SECONDS3 = 30 * 24 * 60 * 60;
|
|
74670
75300
|
function safeReturnTo2(value) {
|
|
74671
75301
|
if (!value || !value.startsWith("/") || value.startsWith("//")) return "/";
|
|
74672
75302
|
return value;
|
|
@@ -74674,15 +75304,12 @@ function safeReturnTo2(value) {
|
|
|
74674
75304
|
function failRedirect(req, env2, reason, returnTo) {
|
|
74675
75305
|
const origin = new URL(req.url).origin;
|
|
74676
75306
|
if (isPlatformHosted(env2)) {
|
|
74677
|
-
|
|
74678
|
-
|
|
74679
|
-
|
|
75307
|
+
return beginPlatformLogin(
|
|
75308
|
+
req,
|
|
75309
|
+
env2,
|
|
75310
|
+
returnTo ?? "/",
|
|
74680
75311
|
reason === "api_only_account" ? "api_only_account" : "instance_login_failed"
|
|
74681
75312
|
);
|
|
74682
|
-
return new Response(null, {
|
|
74683
|
-
status: 302,
|
|
74684
|
-
headers: { Location: target.toString() }
|
|
74685
|
-
});
|
|
74686
75313
|
}
|
|
74687
75314
|
return new Response(null, {
|
|
74688
75315
|
status: 302,
|
|
@@ -74694,7 +75321,9 @@ var callback_get_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
74694
75321
|
return failRedirect(req, env2, "not_hosted");
|
|
74695
75322
|
}
|
|
74696
75323
|
const url = new URL(req.url);
|
|
74697
|
-
const
|
|
75324
|
+
const loginState = consumePlatformLoginState(req, url.searchParams.get("return_to"));
|
|
75325
|
+
const finishLoginState = (response) => loginState.present ? withClearedPlatformLoginState(req, response) : response;
|
|
75326
|
+
const failReturnTo = safeReturnTo2(loginState.returnTo);
|
|
74698
75327
|
const handoff = url.searchParams.get("handoff") || url.searchParams.get("token");
|
|
74699
75328
|
if (!handoff) {
|
|
74700
75329
|
return failRedirect(req, env2, "invalid_response", failReturnTo);
|
|
@@ -74708,29 +75337,37 @@ var callback_get_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
74708
75337
|
projectId: configuredProjectId
|
|
74709
75338
|
}
|
|
74710
75339
|
);
|
|
74711
|
-
if (!payload || !payload.platform_user_id || !payload.role) {
|
|
75340
|
+
if (!payload || !payload.platform_user_id || !payload.role || !payload.jti) {
|
|
74712
75341
|
return failRedirect(req, env2, "invalid_handoff", failReturnTo);
|
|
74713
75342
|
}
|
|
74714
75343
|
if (!configuredProjectId && payload.project_id !== hostedInstanceRedirectId(req, env2)) {
|
|
74715
75344
|
return failRedirect(req, env2, "invalid_handoff", failReturnTo);
|
|
74716
75345
|
}
|
|
74717
75346
|
if (payload.role === "api") {
|
|
74718
|
-
const apiReturnTo =
|
|
75347
|
+
const apiReturnTo = failReturnTo;
|
|
74719
75348
|
if (/^\/api\/auth\/device\/[A-Za-z0-9]{8,64}\/approve$/.test(apiReturnTo)) {
|
|
74720
|
-
return new Response(null, {
|
|
75349
|
+
return finishLoginState(new Response(null, {
|
|
74721
75350
|
status: 302,
|
|
74722
75351
|
headers: {
|
|
74723
75352
|
Location: `${url.origin}${apiReturnTo}?handoff=${encodeURIComponent(handoff)}`
|
|
74724
75353
|
}
|
|
74725
|
-
});
|
|
75354
|
+
}));
|
|
74726
75355
|
}
|
|
74727
75356
|
const landingRaw = env2.STANDARD_AGENTS_API_ROLE_LANDING_URL;
|
|
74728
75357
|
const landing = typeof landingRaw === "string" ? landingRaw.trim() : "";
|
|
74729
75358
|
if (landing && /^https:\/\//.test(landing)) {
|
|
74730
|
-
return
|
|
75359
|
+
return finishLoginState(
|
|
75360
|
+
new Response(null, { status: 302, headers: { Location: landing } })
|
|
75361
|
+
);
|
|
74731
75362
|
}
|
|
74732
75363
|
return failRedirect(req, env2, "api_only_account");
|
|
74733
75364
|
}
|
|
75365
|
+
if (!loginState.valid) {
|
|
75366
|
+
return beginPlatformLogin(req, env2, failReturnTo);
|
|
75367
|
+
}
|
|
75368
|
+
if (!await consumePlatformHandoffJti(env2, payload.jti, payload.exp)) {
|
|
75369
|
+
return failRedirect(req, env2, "invalid_handoff", failReturnTo);
|
|
75370
|
+
}
|
|
74734
75371
|
const session = await mintLocalSessionForPlatformUser(env2, {
|
|
74735
75372
|
platform_user_id: payload.platform_user_id,
|
|
74736
75373
|
username: payload.username ?? null,
|
|
@@ -74740,14 +75377,15 @@ var callback_get_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
74740
75377
|
role: payload.role,
|
|
74741
75378
|
permissions: payload.permissions ?? null
|
|
74742
75379
|
});
|
|
74743
|
-
const returnTo =
|
|
74744
|
-
|
|
74745
|
-
|
|
74746
|
-
headers: {
|
|
74747
|
-
Location: `${url.origin}${returnTo}`,
|
|
74748
|
-
"Set-Cookie": buildSessionCookie(req, session.token, SESSION_TTL_SECONDS2)
|
|
74749
|
-
}
|
|
75380
|
+
const returnTo = failReturnTo;
|
|
75381
|
+
const headers = new Headers({
|
|
75382
|
+
Location: `${url.origin}${returnTo}`
|
|
74750
75383
|
});
|
|
75384
|
+
headers.append("Set-Cookie", buildSessionCookie(req, session.token, SESSION_TTL_SECONDS3));
|
|
75385
|
+
return withClearedPlatformLoginState(req, new Response(null, {
|
|
75386
|
+
status: 302,
|
|
75387
|
+
headers
|
|
75388
|
+
}));
|
|
74751
75389
|
});
|
|
74752
75390
|
|
|
74753
75391
|
// src/api/auth/sa/start.get.ts
|
|
@@ -74757,12 +75395,7 @@ var start_get_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
74757
75395
|
}
|
|
74758
75396
|
const url = new URL(req.url);
|
|
74759
75397
|
const returnTo = url.searchParams.get("return_to") || "/";
|
|
74760
|
-
return
|
|
74761
|
-
status: 302,
|
|
74762
|
-
headers: {
|
|
74763
|
-
Location: platformLoginUrl(req, env2, returnTo)
|
|
74764
|
-
}
|
|
74765
|
-
});
|
|
75398
|
+
return beginPlatformLogin(req, env2, returnTo);
|
|
74766
75399
|
});
|
|
74767
75400
|
|
|
74768
75401
|
// src/api/users/me/[...rest].ts
|
|
@@ -74907,6 +75540,7 @@ var index_delete_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
74907
75540
|
if (!key) {
|
|
74908
75541
|
return Response.json({ error: "key query parameter required" }, { status: 400 });
|
|
74909
75542
|
}
|
|
75543
|
+
if (!isUserKvKeyClientWritable(key)) return reservedKvKeyResponse();
|
|
74910
75544
|
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
74911
75545
|
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
74912
75546
|
if (typeof agentBuilder.setUserValue !== "function") {
|
|
@@ -74977,7 +75611,7 @@ var index_get_default4 = defineController2(async ({ req, env: env2 }) => {
|
|
|
74977
75611
|
});
|
|
74978
75612
|
|
|
74979
75613
|
// src/api/users/me/kv/index.post.ts
|
|
74980
|
-
var
|
|
75614
|
+
var index_post_default7 = defineController2(async ({ req, env: env2 }) => {
|
|
74981
75615
|
try {
|
|
74982
75616
|
const authResult = await requireAuth(req, env2);
|
|
74983
75617
|
if (authResult instanceof Response) {
|
|
@@ -75003,6 +75637,7 @@ var index_post_default8 = defineController2(async ({ req, env: env2 }) => {
|
|
|
75003
75637
|
if (typeof key !== "string" || key.length === 0) {
|
|
75004
75638
|
return Response.json({ error: "key required" }, { status: 400 });
|
|
75005
75639
|
}
|
|
75640
|
+
if (!isUserKvKeyClientWritable(key)) return reservedKvKeyResponse();
|
|
75006
75641
|
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
75007
75642
|
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
75008
75643
|
if (typeof agentBuilder.setUserValue !== "function") {
|
|
@@ -75041,13 +75676,39 @@ var stream_default3 = defineController2(async ({ req, env: env2 }) => {
|
|
|
75041
75676
|
return forwardToUserScope(req, env2, authResult.user.id, "stream");
|
|
75042
75677
|
});
|
|
75043
75678
|
|
|
75044
|
-
// src/api/auth/device/[code]/
|
|
75679
|
+
// src/api/auth/device/[code]/_approval.ts
|
|
75680
|
+
var CONFIRMATION_TTL_SECONDS = 5 * 60;
|
|
75681
|
+
function escapeHtml(value) {
|
|
75682
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
75683
|
+
}
|
|
75045
75684
|
function page(title, body, ok) {
|
|
75046
75685
|
return new Response(
|
|
75047
|
-
`<!doctype html><html><head><meta charset="utf-8"><title>${title}</title><style>body{background:#0a0c10;color:#e8ecf3;font:16px/1.6 ui-sans-serif,system-ui;display:flex;min-height:100vh;align-items:center;justify-content:center}
|
|
75048
|
-
{
|
|
75686
|
+
`<!doctype html><html><head><meta charset="utf-8"><meta name="referrer" content="no-referrer"><title>${escapeHtml(title)}</title><style>body{background:#0a0c10;color:#e8ecf3;font:16px/1.6 ui-sans-serif,system-ui;display:flex;min-height:100vh;align-items:center;justify-content:center}main{max-width:420px;text-align:center;padding:40px;border:1px solid #232936;border-radius:14px;background:#11141b}h1{font-size:22px;color:${ok ? "#2dd4bf" : "#f87171"}}p{color:#8b93a7;margin-top:10px}</style></head><body><main><h1>${escapeHtml(title)}</h1><p>${escapeHtml(body)}</p></main></body></html>`,
|
|
75687
|
+
{
|
|
75688
|
+
headers: {
|
|
75689
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
75690
|
+
"Cache-Control": "no-store",
|
|
75691
|
+
"Referrer-Policy": "no-referrer",
|
|
75692
|
+
"X-Content-Type-Options": "nosniff"
|
|
75693
|
+
}
|
|
75694
|
+
}
|
|
75049
75695
|
);
|
|
75050
75696
|
}
|
|
75697
|
+
function confirmationPage(req, code, confirmationToken, handoff) {
|
|
75698
|
+
const url = new URL(req.url);
|
|
75699
|
+
const handoffInput = handoff ? `<input type="hidden" name="handoff" value="${escapeHtml(handoff)}">` : "";
|
|
75700
|
+
const shortCode = code.length > 12 ? `${code.slice(0, 6)}\u2026${code.slice(-6)}` : code;
|
|
75701
|
+
const html = `<!doctype html><html><head><meta charset="utf-8"><meta name="referrer" content="no-referrer"><title>Approve device sign-in</title><style>body{background:#0a0c10;color:#e8ecf3;font:16px/1.6 ui-sans-serif,system-ui;display:flex;min-height:100vh;align-items:center;justify-content:center}main{max-width:440px;text-align:center;padding:40px;border:1px solid #232936;border-radius:14px;background:#11141b}h1{font-size:22px}p{color:#a5adbd}.code{font:600 18px ui-monospace,monospace;letter-spacing:.08em;color:#e8ecf3}form{display:flex;gap:12px;justify-content:center;margin-top:26px}button,a{border-radius:9px;padding:10px 18px;font:inherit;text-decoration:none}button{border:0;background:#2dd4bf;color:#07110f;font-weight:700;cursor:pointer}a{border:1px solid #394150;color:#cbd5e1}</style></head><body><main><h1>Approve device sign-in?</h1><p>A command-line client is requesting a personal instance API key for your account.</p><p class="code">${escapeHtml(shortCode)}</p><form method="post" action="${escapeHtml(url.pathname)}"><input type="hidden" name="confirmation_token" value="${escapeHtml(confirmationToken)}">${handoffInput}<button type="submit">Approve device</button><a href="/">Cancel</a></form></main></body></html>`;
|
|
75702
|
+
return new Response(html, {
|
|
75703
|
+
headers: {
|
|
75704
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
75705
|
+
"Cache-Control": "no-store",
|
|
75706
|
+
"Referrer-Policy": "no-referrer",
|
|
75707
|
+
"X-Content-Type-Options": "nosniff",
|
|
75708
|
+
"Content-Security-Policy": "default-src 'none'; style-src 'unsafe-inline'; form-action 'self'; base-uri 'none'; frame-ancestors 'none'"
|
|
75709
|
+
}
|
|
75710
|
+
});
|
|
75711
|
+
}
|
|
75051
75712
|
function outcome(env2, ok, reason, fallback) {
|
|
75052
75713
|
const baseRaw = env2.STANDARD_AGENTS_DEVICE_OUTCOME_URL_BASE;
|
|
75053
75714
|
const base = typeof baseRaw === "string" ? baseRaw.trim().replace(/\/+$/, "") : "";
|
|
@@ -75057,12 +75718,9 @@ function outcome(env2, ok, reason, fallback) {
|
|
|
75057
75718
|
}
|
|
75058
75719
|
return page(fallback.title, fallback.body, ok);
|
|
75059
75720
|
}
|
|
75060
|
-
|
|
75061
|
-
const code = params.code;
|
|
75062
|
-
if (!code) return outcome(env2, false, "invalid_link", { title: "Missing code", body: "This device link is malformed." });
|
|
75721
|
+
async function resolveDeviceApprovalIdentity(req, env2) {
|
|
75063
75722
|
const url = new URL(req.url);
|
|
75064
|
-
|
|
75065
|
-
const handoff = url.searchParams.get("handoff");
|
|
75723
|
+
const handoff = url.searchParams.get("handoff") ?? (req.method === "POST" ? (await req.clone().formData().catch(() => null))?.get("handoff")?.toString() ?? null : null);
|
|
75066
75724
|
if (handoff && isPlatformHosted(env2)) {
|
|
75067
75725
|
const configuredProjectId = typeof env2.STANDARD_AGENTS_PROJECT_ID === "string" ? env2.STANDARD_AGENTS_PROJECT_ID : void 0;
|
|
75068
75726
|
const payload = await verifyPlatformSignedPayload(
|
|
@@ -75071,10 +75729,13 @@ var approve_get_default = defineController2(async ({ req, env: env2, params }) =
|
|
|
75071
75729
|
{ kind: "instance_handoff", projectId: configuredProjectId }
|
|
75072
75730
|
);
|
|
75073
75731
|
const projectOk = payload && (configuredProjectId || payload.project_id === hostedInstanceRedirectId(req, env2));
|
|
75074
|
-
if (!payload || !payload.platform_user_id || !payload.role || !projectOk) {
|
|
75075
|
-
return outcome(env2, false, "signin_failed", {
|
|
75732
|
+
if (!payload || !payload.platform_user_id || !payload.role || !payload.jti || !projectOk) {
|
|
75733
|
+
return outcome(env2, false, "signin_failed", {
|
|
75734
|
+
title: "Sign in failed",
|
|
75735
|
+
body: "This sign-in link is invalid or has expired. Start again from your terminal."
|
|
75736
|
+
});
|
|
75076
75737
|
}
|
|
75077
|
-
const
|
|
75738
|
+
const platformProfile = {
|
|
75078
75739
|
platform_user_id: payload.platform_user_id,
|
|
75079
75740
|
username: payload.username ?? null,
|
|
75080
75741
|
display_name: payload.display_name ?? null,
|
|
@@ -75082,27 +75743,163 @@ var approve_get_default = defineController2(async ({ req, env: env2, params }) =
|
|
|
75082
75743
|
avatar_url: payload.avatar_url ?? null,
|
|
75083
75744
|
role: payload.role,
|
|
75084
75745
|
permissions: payload.permissions ?? null
|
|
75085
|
-
}
|
|
75086
|
-
|
|
75087
|
-
|
|
75088
|
-
|
|
75089
|
-
|
|
75090
|
-
|
|
75091
|
-
|
|
75092
|
-
|
|
75093
|
-
|
|
75094
|
-
}
|
|
75095
|
-
|
|
75096
|
-
|
|
75746
|
+
};
|
|
75747
|
+
return {
|
|
75748
|
+
confirmationSubject: `platform:${payload.platform_user_id}`,
|
|
75749
|
+
handoff,
|
|
75750
|
+
platformProfile,
|
|
75751
|
+
platformHandoff: {
|
|
75752
|
+
jti: payload.jti,
|
|
75753
|
+
expires_at: payload.exp
|
|
75754
|
+
}
|
|
75755
|
+
};
|
|
75756
|
+
}
|
|
75757
|
+
const authResult = await requireAuth(req, env2);
|
|
75758
|
+
if (authResult instanceof Response) {
|
|
75759
|
+
if (req.method !== "GET") {
|
|
75760
|
+
return outcome(env2, false, "session_required", {
|
|
75761
|
+
title: "Sign in required",
|
|
75762
|
+
body: "Return to the device link and sign in again before approving."
|
|
75763
|
+
});
|
|
75097
75764
|
}
|
|
75098
|
-
|
|
75765
|
+
const returnTo = encodeURIComponent(url.pathname);
|
|
75766
|
+
const hosted = Boolean(
|
|
75767
|
+
env2.STANDARD_AGENTS_HOSTED && String(env2.STANDARD_AGENTS_HOSTED) !== "0" && String(env2.STANDARD_AGENTS_HOSTED).toLowerCase() !== "false"
|
|
75768
|
+
);
|
|
75769
|
+
const target = hosted ? `/api/auth/sa/start?return_to=${returnTo}` : `/login?return_to=${returnTo}`;
|
|
75770
|
+
return new Response(null, { status: 302, headers: { Location: `${url.origin}${target}` } });
|
|
75771
|
+
}
|
|
75772
|
+
if (authResult.authType === "api_key") {
|
|
75773
|
+
return outcome(env2, false, "session_required", {
|
|
75774
|
+
title: "Sign in required",
|
|
75775
|
+
body: "Device logins must be approved from a signed-in browser session."
|
|
75776
|
+
});
|
|
75777
|
+
}
|
|
75778
|
+
return {
|
|
75779
|
+
confirmationSubject: `user:${authResult.user.id}`,
|
|
75780
|
+
handoff: null,
|
|
75781
|
+
localUserId: authResult.user.id
|
|
75782
|
+
};
|
|
75783
|
+
}
|
|
75784
|
+
async function consumeDeviceApprovalHandoff(env2, identity) {
|
|
75785
|
+
if (!identity.platformHandoff) return true;
|
|
75786
|
+
return consumePlatformHandoffJti(
|
|
75787
|
+
env2,
|
|
75788
|
+
identity.platformHandoff.jti,
|
|
75789
|
+
identity.platformHandoff.expires_at
|
|
75790
|
+
);
|
|
75791
|
+
}
|
|
75792
|
+
async function materializeDeviceApprovalUser(env2, identity) {
|
|
75793
|
+
if (identity.localUserId) return identity.localUserId;
|
|
75794
|
+
if (!identity.platformProfile) {
|
|
75795
|
+
throw new Error("Device approval identity is missing a local user and platform profile");
|
|
75796
|
+
}
|
|
75797
|
+
const user = await upsertReplicaUserForPlatformProfile(
|
|
75798
|
+
env2,
|
|
75799
|
+
identity.platformProfile
|
|
75800
|
+
);
|
|
75801
|
+
return user.id;
|
|
75802
|
+
}
|
|
75803
|
+
function encryptionKey(env2) {
|
|
75804
|
+
const value = env2.ENCRYPTION_KEY;
|
|
75805
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
75806
|
+
}
|
|
75807
|
+
async function createDeviceConfirmationToken(env2, code, confirmationSubject) {
|
|
75808
|
+
const key = encryptionKey(env2);
|
|
75809
|
+
if (!key) return null;
|
|
75810
|
+
return signToken(JSON.stringify({
|
|
75811
|
+
kind: "device_approval_confirmation",
|
|
75812
|
+
code_hash: await hashToken(code),
|
|
75813
|
+
subject: confirmationSubject,
|
|
75814
|
+
exp: Math.floor(Date.now() / 1e3) + CONFIRMATION_TTL_SECONDS,
|
|
75815
|
+
nonce: crypto.randomUUID()
|
|
75816
|
+
}), key);
|
|
75817
|
+
}
|
|
75818
|
+
async function verifyDeviceConfirmationToken(env2, code, confirmationSubject, token) {
|
|
75819
|
+
const key = encryptionKey(env2);
|
|
75820
|
+
if (!key) return false;
|
|
75821
|
+
const raw = await verifySignedToken(token, key);
|
|
75822
|
+
if (!raw) return false;
|
|
75823
|
+
try {
|
|
75824
|
+
const payload = JSON.parse(raw);
|
|
75825
|
+
return payload.kind === "device_approval_confirmation" && payload.code_hash === await hashToken(code) && payload.subject === confirmationSubject && typeof payload.exp === "number" && payload.exp >= Math.floor(Date.now() / 1e3);
|
|
75826
|
+
} catch {
|
|
75827
|
+
return false;
|
|
75828
|
+
}
|
|
75829
|
+
}
|
|
75830
|
+
function isSameOriginApprovalPost(req) {
|
|
75831
|
+
const url = new URL(req.url);
|
|
75832
|
+
const origin = req.headers.get("Origin");
|
|
75833
|
+
if (origin && origin !== url.origin) return false;
|
|
75834
|
+
const fetchSite = req.headers.get("Sec-Fetch-Site");
|
|
75835
|
+
return !fetchSite || fetchSite === "same-origin" || fetchSite === "none";
|
|
75836
|
+
}
|
|
75837
|
+
|
|
75838
|
+
// src/api/auth/device/[code]/approve.get.ts
|
|
75839
|
+
var approve_get_default = defineController2(async ({ req, env: env2, params }) => {
|
|
75840
|
+
const code = params.code;
|
|
75841
|
+
if (!code) {
|
|
75842
|
+
return outcome(env2, false, "invalid_link", {
|
|
75843
|
+
title: "Missing code",
|
|
75844
|
+
body: "This device link is malformed."
|
|
75845
|
+
});
|
|
75846
|
+
}
|
|
75847
|
+
const identity = await resolveDeviceApprovalIdentity(req, env2);
|
|
75848
|
+
if (identity instanceof Response) return identity;
|
|
75849
|
+
const confirmationToken = await createDeviceConfirmationToken(
|
|
75850
|
+
env2,
|
|
75851
|
+
code,
|
|
75852
|
+
identity.confirmationSubject
|
|
75853
|
+
);
|
|
75854
|
+
if (!confirmationToken) {
|
|
75855
|
+
return outcome(env2, false, "signin_failed", {
|
|
75856
|
+
title: "Sign in failed",
|
|
75857
|
+
body: "This instance cannot create a secure device confirmation. Contact its administrator."
|
|
75858
|
+
});
|
|
75099
75859
|
}
|
|
75860
|
+
return confirmationPage(req, code, confirmationToken, identity.handoff);
|
|
75861
|
+
});
|
|
75862
|
+
|
|
75863
|
+
// src/api/auth/device/[code]/approve.post.ts
|
|
75864
|
+
var approve_post_default = defineController2(async ({ req, env: env2, params }) => {
|
|
75865
|
+
const code = params.code;
|
|
75866
|
+
if (!code) {
|
|
75867
|
+
return outcome(env2, false, "invalid_link", {
|
|
75868
|
+
title: "Missing code",
|
|
75869
|
+
body: "This device link is malformed."
|
|
75870
|
+
});
|
|
75871
|
+
}
|
|
75872
|
+
if (!isSameOriginApprovalPost(req)) {
|
|
75873
|
+
return Response.json({ error: "Cross-origin device approval refused" }, { status: 403 });
|
|
75874
|
+
}
|
|
75875
|
+
const form = await req.clone().formData().catch(() => null);
|
|
75876
|
+
const confirmationToken = form?.get("confirmation_token")?.toString() ?? "";
|
|
75877
|
+
if (!confirmationToken) {
|
|
75878
|
+
return Response.json({ error: "Device confirmation token required" }, { status: 403 });
|
|
75879
|
+
}
|
|
75880
|
+
const identity = await resolveDeviceApprovalIdentity(req, env2);
|
|
75881
|
+
if (identity instanceof Response) return identity;
|
|
75882
|
+
if (!await verifyDeviceConfirmationToken(
|
|
75883
|
+
env2,
|
|
75884
|
+
code,
|
|
75885
|
+
identity.confirmationSubject,
|
|
75886
|
+
confirmationToken
|
|
75887
|
+
)) {
|
|
75888
|
+
return Response.json({ error: "Invalid or expired device confirmation" }, { status: 403 });
|
|
75889
|
+
}
|
|
75890
|
+
if (!await consumeDeviceApprovalHandoff(env2, identity)) {
|
|
75891
|
+
return outcome(env2, false, "signin_failed", {
|
|
75892
|
+
title: "Sign in failed",
|
|
75893
|
+
body: "This sign-in link was already used or has expired. Start again from your terminal."
|
|
75894
|
+
});
|
|
75895
|
+
}
|
|
75896
|
+
const userId = await materializeDeviceApprovalUser(env2, identity);
|
|
75100
75897
|
const token = generateApiKey();
|
|
75101
75898
|
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
75102
75899
|
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
75103
75900
|
const ok = await agentBuilder.approveDeviceLogin({
|
|
75104
75901
|
code_hash: await hashToken(code),
|
|
75105
|
-
user_id:
|
|
75902
|
+
user_id: userId,
|
|
75106
75903
|
token,
|
|
75107
75904
|
token_hash: await hashToken(token),
|
|
75108
75905
|
key_prefix: token.slice(0, 12),
|
|
@@ -75110,12 +75907,19 @@ var approve_get_default = defineController2(async ({ req, env: env2, params }) =
|
|
|
75110
75907
|
key_name: "CLI device login"
|
|
75111
75908
|
});
|
|
75112
75909
|
if (!ok) {
|
|
75113
|
-
return outcome(env2, false, "expired", {
|
|
75910
|
+
return outcome(env2, false, "expired", {
|
|
75911
|
+
title: "Link expired",
|
|
75912
|
+
body: "This device login has expired or was already used. Start again from your terminal."
|
|
75913
|
+
});
|
|
75114
75914
|
}
|
|
75115
|
-
return outcome(env2, true, "done", {
|
|
75915
|
+
return outcome(env2, true, "done", {
|
|
75916
|
+
title: "You're connected",
|
|
75917
|
+
body: "Standard Code is now signed in. Return to your terminal \u2014 it will pick up automatically."
|
|
75918
|
+
});
|
|
75116
75919
|
});
|
|
75117
75920
|
|
|
75118
75921
|
// src/api/skills/[name]/files/[...path].get.ts
|
|
75922
|
+
init_scope();
|
|
75119
75923
|
var path_get_default = defineController2(async ({ req, env: env2, params }) => {
|
|
75120
75924
|
const authResult = await requireAdmin(req, env2);
|
|
75121
75925
|
if (authResult instanceof Response) return authResult;
|
|
@@ -75128,7 +75932,11 @@ var path_get_default = defineController2(async ({ req, env: env2, params }) => {
|
|
|
75128
75932
|
const agentBuilderId = env2.AGENT_BUILDER.idFromName("singleton");
|
|
75129
75933
|
const agentBuilder = env2.AGENT_BUILDER.get(agentBuilderId);
|
|
75130
75934
|
try {
|
|
75131
|
-
const content = await agentBuilder.getSkillFile(
|
|
75935
|
+
const content = await agentBuilder.getSkillFile(
|
|
75936
|
+
{ ownerId: SHARED_SKILL_OWNER },
|
|
75937
|
+
name15,
|
|
75938
|
+
filePath
|
|
75939
|
+
);
|
|
75132
75940
|
if (content === null) {
|
|
75133
75941
|
return Response.json({ error: `File not found: ${filePath} in skill ${name15}` }, { status: 404 });
|
|
75134
75942
|
}
|
|
@@ -75143,6 +75951,24 @@ var path_get_default = defineController2(async ({ req, env: env2, params }) => {
|
|
|
75143
75951
|
|
|
75144
75952
|
// src/api/threads/[id]/fs/[...path].ts
|
|
75145
75953
|
var CHUNK_SIZE2 = 1.75 * 1024 * 1024;
|
|
75954
|
+
var EXECUTABLE_DOCUMENT_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
75955
|
+
"text/html",
|
|
75956
|
+
"image/svg+xml",
|
|
75957
|
+
"application/xhtml+xml"
|
|
75958
|
+
]);
|
|
75959
|
+
function safeDownloadName(name15) {
|
|
75960
|
+
return name15.replace(/["\\\r\n]/g, "_");
|
|
75961
|
+
}
|
|
75962
|
+
function fileResponseHeaders(file) {
|
|
75963
|
+
const mimeType = file.mimeType.split(";", 1)[0]?.trim().toLowerCase();
|
|
75964
|
+
const disposition = mimeType && EXECUTABLE_DOCUMENT_MIME_TYPES.has(mimeType) ? "attachment" : "inline";
|
|
75965
|
+
return {
|
|
75966
|
+
"Content-Type": file.mimeType,
|
|
75967
|
+
"Content-Length": String(file.size),
|
|
75968
|
+
"Content-Disposition": `${disposition}; filename="${safeDownloadName(file.name)}"`,
|
|
75969
|
+
"X-Content-Type-Options": "nosniff"
|
|
75970
|
+
};
|
|
75971
|
+
}
|
|
75146
75972
|
function toAttachmentRef(file) {
|
|
75147
75973
|
const metadata = file.metadata;
|
|
75148
75974
|
const width = file.width ?? metadata?.width;
|
|
@@ -75233,8 +76059,9 @@ async function handleGet2(stub, path10, url) {
|
|
|
75233
76059
|
headers: {
|
|
75234
76060
|
"Content-Type": "image/jpeg",
|
|
75235
76061
|
// Thumbnails are typically JPEG
|
|
75236
|
-
"Cache-Control": "public, max-age=31536000"
|
|
76062
|
+
"Cache-Control": "public, max-age=31536000",
|
|
75237
76063
|
// Cache for 1 year
|
|
76064
|
+
"X-Content-Type-Options": "nosniff"
|
|
75238
76065
|
}
|
|
75239
76066
|
});
|
|
75240
76067
|
}
|
|
@@ -75274,11 +76101,7 @@ async function handleGet2(stub, path10, url) {
|
|
|
75274
76101
|
bytes[i] = binary.charCodeAt(i);
|
|
75275
76102
|
}
|
|
75276
76103
|
return new Response(bytes, {
|
|
75277
|
-
headers:
|
|
75278
|
-
"Content-Type": file.mimeType,
|
|
75279
|
-
"Content-Length": String(file.size),
|
|
75280
|
-
"Content-Disposition": `inline; filename="${file.name}"`
|
|
75281
|
-
}
|
|
76104
|
+
headers: fileResponseHeaders(file)
|
|
75282
76105
|
});
|
|
75283
76106
|
}
|
|
75284
76107
|
function streamChunkedFile(stub, path10, file) {
|
|
@@ -75306,12 +76129,8 @@ function streamChunkedFile(stub, path10, file) {
|
|
|
75306
76129
|
}
|
|
75307
76130
|
})();
|
|
75308
76131
|
return new Response(readable, {
|
|
75309
|
-
|
|
75310
|
-
|
|
75311
|
-
"Content-Length": String(file.size),
|
|
75312
|
-
"Content-Disposition": `inline; filename="${file.name}"`
|
|
75313
|
-
// Note: We set Content-Length, but also use chunked transfer internally
|
|
75314
|
-
}
|
|
76132
|
+
// Note: We set Content-Length, but also use chunked transfer internally.
|
|
76133
|
+
headers: fileResponseHeaders(file)
|
|
75315
76134
|
});
|
|
75316
76135
|
}
|
|
75317
76136
|
async function handlePost2(stub, path10, req) {
|
|
@@ -75508,19 +76327,9 @@ async function handleChunkedUploadComplete(stub, filePath, req) {
|
|
|
75508
76327
|
|
|
75509
76328
|
// src/api/threads/[id]/logs/[logId].get.ts
|
|
75510
76329
|
var logId_get_default = defineController2(async ({ req, params, env: env2 }) => {
|
|
75511
|
-
|
|
75512
|
-
|
|
75513
|
-
|
|
75514
|
-
return authResult;
|
|
75515
|
-
}
|
|
75516
|
-
} else {
|
|
75517
|
-
const authContext = await authenticate(req, env2);
|
|
75518
|
-
if (authContext && !hasPermission(authContext.user, "logs")) {
|
|
75519
|
-
return Response.json(
|
|
75520
|
-
{ error: "Forbidden: 'logs' access required" },
|
|
75521
|
-
{ status: 403 }
|
|
75522
|
-
);
|
|
75523
|
-
}
|
|
76330
|
+
const authResult = await requirePermission(req, env2, "logs");
|
|
76331
|
+
if (authResult instanceof Response) {
|
|
76332
|
+
return authResult;
|
|
75524
76333
|
}
|
|
75525
76334
|
const threadId = params.id;
|
|
75526
76335
|
const logId = params.logId;
|
|
@@ -75932,19 +76741,9 @@ function createInspectProviderConfig(providerName, factory, env2) {
|
|
|
75932
76741
|
};
|
|
75933
76742
|
}
|
|
75934
76743
|
var provider_get_default = defineController2(async ({ req, params, env: env2 }) => {
|
|
75935
|
-
|
|
75936
|
-
|
|
75937
|
-
|
|
75938
|
-
return authResult;
|
|
75939
|
-
}
|
|
75940
|
-
} else {
|
|
75941
|
-
const authContext = await authenticate(req, env2);
|
|
75942
|
-
if (authContext && !hasPermission(authContext.user, "logs")) {
|
|
75943
|
-
return Response.json(
|
|
75944
|
-
{ error: "Forbidden: 'logs' access required" },
|
|
75945
|
-
{ status: 403 }
|
|
75946
|
-
);
|
|
75947
|
-
}
|
|
76744
|
+
const authResult = await requirePermission(req, env2, "logs");
|
|
76745
|
+
if (authResult instanceof Response) {
|
|
76746
|
+
return authResult;
|
|
75948
76747
|
}
|
|
75949
76748
|
const threadId = params.id;
|
|
75950
76749
|
const logId = params.logId;
|
|
@@ -76164,30 +76963,28 @@ var provider_get_default = defineController2(async ({ req, params, env: env2 })
|
|
|
76164
76963
|
|
|
76165
76964
|
// src/built-in-routes.ts
|
|
76166
76965
|
var routeHandlers = {
|
|
76167
|
-
"POST:/": index_post_default,
|
|
76168
76966
|
"GET:/agents": agents_get_default,
|
|
76169
76967
|
"GET:/api-keys": index_get_default,
|
|
76170
|
-
"POST:/api-keys":
|
|
76968
|
+
"POST:/api-keys": index_post_default,
|
|
76171
76969
|
"GET:/config": config_get_default,
|
|
76172
76970
|
"GET:/diagnostics": diagnostics_get_default,
|
|
76173
76971
|
"GET:/events": events_get_default,
|
|
76174
76972
|
"GET:/hooks": hooks_get_default,
|
|
76175
76973
|
"GET:/models": models_get_default,
|
|
76176
|
-
"GET:/new-test": new_test_get_default,
|
|
76177
76974
|
"GET:/platform-endpoint": platform_endpoint_default,
|
|
76178
76975
|
"GET:/prompts": prompts_get_default,
|
|
76179
76976
|
"GET:/providers": providers_get_default,
|
|
76180
76977
|
"GET:/skills": index_get_default2,
|
|
76181
|
-
"POST:/skills":
|
|
76182
|
-
"POST:/threads":
|
|
76978
|
+
"POST:/skills": index_post_default2,
|
|
76979
|
+
"POST:/threads": index_post_default3,
|
|
76183
76980
|
"GET:/threads": threads_default,
|
|
76184
76981
|
"GET:/tools": tools_get_default,
|
|
76185
76982
|
"GET:/users": index_get_default3,
|
|
76186
|
-
"POST:/users":
|
|
76983
|
+
"POST:/users": index_post_default4,
|
|
76187
76984
|
"GET:/agents/:name": name_get_default,
|
|
76188
76985
|
"DELETE:/api-keys/:id": id_delete_default,
|
|
76189
76986
|
"GET:/models/:name": name_get_default2,
|
|
76190
|
-
"POST:/pack/:agentName":
|
|
76987
|
+
"POST:/pack/:agentName": index_post_default5,
|
|
76191
76988
|
"GET:/prompts/:name": name_get_default3,
|
|
76192
76989
|
"DELETE:/skills/:name": name_delete_default,
|
|
76193
76990
|
"GET:/skills/:name": name_get_default4,
|
|
@@ -76196,18 +76993,19 @@ var routeHandlers = {
|
|
|
76196
76993
|
"PATCH:/threads/:id": id_patch_default,
|
|
76197
76994
|
"GET:/threads/:id": id_default,
|
|
76198
76995
|
"GET:/tools/:name": name_get_default5,
|
|
76199
|
-
"POST:/unpack/:packageId":
|
|
76996
|
+
"POST:/unpack/:packageId": index_post_default6,
|
|
76200
76997
|
"DELETE:/users/:id": id_delete_default3,
|
|
76201
76998
|
"PUT:/users/:id": id_put_default,
|
|
76202
76999
|
"POST:/auth/bootstrap": bootstrap_post_default,
|
|
76203
77000
|
"POST:/auth/brolly-control": brolly_control_post_default,
|
|
76204
77001
|
"GET:/auth/config": config_get_default2,
|
|
77002
|
+
"DELETE:/auth/current-key": current_key_delete_default,
|
|
76205
77003
|
"POST:/auth/login": login_post_default,
|
|
76206
|
-
"GET:/auth/logout": logout_get_default,
|
|
76207
77004
|
"POST:/auth/logout": logout_post_default,
|
|
76208
77005
|
"GET:/auth/me": me_get_default,
|
|
76209
77006
|
"POST:/auth/platform-cleanup": platform_cleanup_post_default,
|
|
76210
77007
|
"POST:/auth/platform-replica": platform_replica_post_default,
|
|
77008
|
+
"POST:/auth/websocket-ticket": websocket_ticket_post_default,
|
|
76211
77009
|
"GET:/envs/instance": instance_get_default,
|
|
76212
77010
|
"PATCH:/envs/instance": instance_patch_default,
|
|
76213
77011
|
"POST:/models/available": available_post_default,
|
|
@@ -76283,9 +77081,10 @@ var routeHandlers = {
|
|
|
76283
77081
|
"GET:/users/me/hub": hub_default,
|
|
76284
77082
|
"DELETE:/users/me/kv": index_delete_default,
|
|
76285
77083
|
"GET:/users/me/kv": index_get_default4,
|
|
76286
|
-
"POST:/users/me/kv":
|
|
77084
|
+
"POST:/users/me/kv": index_post_default7,
|
|
76287
77085
|
"GET:/users/me/stream": stream_default3,
|
|
76288
77086
|
"GET:/auth/device/:code/approve": approve_get_default,
|
|
77087
|
+
"POST:/auth/device/:code/approve": approve_post_default,
|
|
76289
77088
|
"GET:/skills/:name/files/**": path_get_default,
|
|
76290
77089
|
"DELETE:/threads/:id/fs/**": path_default3,
|
|
76291
77090
|
"POST:/threads/:id/fs/**": path_default3,
|