@standardagents/builder 0.41.15 → 0.41.17
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 +160 -14
- package/dist/built-in-routes.js.map +1 -1
- package/dist/{index-ChHAVogf.d.ts → index-C82dLGPq.d.ts} +14 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +126 -30
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts +21 -1
- package/dist/plugin.js +36 -10
- package/dist/plugin.js.map +1 -1
- package/dist/{resolver-DE5HFRlb.d.ts → resolver-eygn_O1w.d.ts} +12 -4
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.js +90 -20
- package/dist/runtime.js.map +1 -1
- package/dist/test.d.ts +1 -1
- package/package.json +5 -5
package/dist/built-in-routes.js
CHANGED
|
@@ -9948,6 +9948,24 @@ var init_platform_handoff_jtis = __esm({
|
|
|
9948
9948
|
}
|
|
9949
9949
|
});
|
|
9950
9950
|
|
|
9951
|
+
// src/durable-objects/agentbuilder-migrations/0022_application_roles.ts
|
|
9952
|
+
var migration60;
|
|
9953
|
+
var init_application_roles = __esm({
|
|
9954
|
+
"src/durable-objects/agentbuilder-migrations/0022_application_roles.ts"() {
|
|
9955
|
+
migration60 = {
|
|
9956
|
+
version: 22,
|
|
9957
|
+
async up(sql) {
|
|
9958
|
+
sql.exec(`CREATE TABLE platform_application_roles (
|
|
9959
|
+
platform_user_id TEXT PRIMARY KEY,
|
|
9960
|
+
roles TEXT NOT NULL DEFAULT '[]',
|
|
9961
|
+
roles_version INTEGER NOT NULL DEFAULT 0
|
|
9962
|
+
)`);
|
|
9963
|
+
sql.exec(`INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '22')`);
|
|
9964
|
+
}
|
|
9965
|
+
};
|
|
9966
|
+
}
|
|
9967
|
+
});
|
|
9968
|
+
|
|
9951
9969
|
// src/durable-objects/agentbuilder-migrations/index.ts
|
|
9952
9970
|
var migrations2;
|
|
9953
9971
|
var init_agentbuilder_migrations = __esm({
|
|
@@ -9973,9 +9991,10 @@ var init_agentbuilder_migrations = __esm({
|
|
|
9973
9991
|
init_scope_skills();
|
|
9974
9992
|
init_websocket_tickets();
|
|
9975
9993
|
init_platform_handoff_jtis();
|
|
9976
|
-
|
|
9994
|
+
init_application_roles();
|
|
9995
|
+
migrations2 = [migration39, migration40, migration41, migration42, migration43, migration44, migration45, migration46, migration47, migration48, migration49, migration50, migration51, migration52, migration53, migration54, migration55, migration56, migration57, migration58, migration59, migration60];
|
|
9977
9996
|
migrations2.reduce(
|
|
9978
|
-
(max,
|
|
9997
|
+
(max, migration61) => Math.max(max, migration61.version),
|
|
9979
9998
|
0
|
|
9980
9999
|
);
|
|
9981
10000
|
}
|
|
@@ -13781,9 +13800,9 @@ var init_DurableThread = __esm({
|
|
|
13781
13800
|
* Each migration is run in order, starting from the current version + 1.
|
|
13782
13801
|
*/
|
|
13783
13802
|
async runMigrations(fromVersion) {
|
|
13784
|
-
for (const
|
|
13785
|
-
if (
|
|
13786
|
-
await
|
|
13803
|
+
for (const migration61 of migrations) {
|
|
13804
|
+
if (migration61.version > fromVersion) {
|
|
13805
|
+
await migration61.up(this.ctx.storage.sql);
|
|
13787
13806
|
}
|
|
13788
13807
|
}
|
|
13789
13808
|
}
|
|
@@ -25378,6 +25397,7 @@ var init_ThreadStateImpl = __esm({
|
|
|
25378
25397
|
username: user.username,
|
|
25379
25398
|
role: user.role,
|
|
25380
25399
|
permissions: user.permissions ?? null,
|
|
25400
|
+
roles: user.roles ?? [],
|
|
25381
25401
|
email: user.email ?? null,
|
|
25382
25402
|
display_name: user.display_name ?? null,
|
|
25383
25403
|
avatar_url: user.avatar_url ?? null
|
|
@@ -78945,6 +78965,8 @@ function parseWebSocketTicketAuth(authJson) {
|
|
|
78945
78965
|
if (typeof user.id !== "string" || typeof user.username !== "string" || typeof user.role !== "string" || record24.authType !== "super_admin" && record24.authType !== "session" && record24.authType !== "api_key") {
|
|
78946
78966
|
return null;
|
|
78947
78967
|
}
|
|
78968
|
+
const roles = user.roles;
|
|
78969
|
+
if (roles !== void 0 && (!Array.isArray(roles) || !roles.every((role) => typeof role === "string"))) return null;
|
|
78948
78970
|
const permissions = user.permissions;
|
|
78949
78971
|
if (permissions !== void 0 && permissions !== null && (!Array.isArray(permissions) || !permissions.every((permission) => typeof permission === "string"))) {
|
|
78950
78972
|
return null;
|
|
@@ -78956,6 +78978,7 @@ function parseWebSocketTicketAuth(authJson) {
|
|
|
78956
78978
|
username: user.username,
|
|
78957
78979
|
role: user.role,
|
|
78958
78980
|
permissions,
|
|
78981
|
+
roles: Array.isArray(roles) ? roles : [],
|
|
78959
78982
|
platform_user_id: typeof user.platform_user_id === "string" ? user.platform_user_id : null,
|
|
78960
78983
|
email: typeof user.email === "string" ? user.email : null,
|
|
78961
78984
|
display_name: typeof user.display_name === "string" ? user.display_name : null,
|
|
@@ -78979,7 +79002,19 @@ async function consumeWebSocketTicket(request, env2) {
|
|
|
78979
79002
|
ticket_hash: await hashToken(ticket),
|
|
78980
79003
|
pathname: url.pathname
|
|
78981
79004
|
});
|
|
78982
|
-
|
|
79005
|
+
const context = typeof authJson === "string" ? parseWebSocketTicketAuth(authJson) : null;
|
|
79006
|
+
if (!context || context.authType === "super_admin") return context;
|
|
79007
|
+
const user = await getAgentBuilder(env2).getUserById(context.user.id);
|
|
79008
|
+
if (!user) return null;
|
|
79009
|
+
return {
|
|
79010
|
+
...context,
|
|
79011
|
+
user: {
|
|
79012
|
+
...context.user,
|
|
79013
|
+
role: user.role,
|
|
79014
|
+
permissions: parsePermissions(user.permissions),
|
|
79015
|
+
roles: user.roles ?? []
|
|
79016
|
+
}
|
|
79017
|
+
};
|
|
78983
79018
|
}
|
|
78984
79019
|
function isWebSocketTicketPath(pathname) {
|
|
78985
79020
|
if (!pathname.startsWith("/api/") || pathname.includes("?") || pathname.includes("#")) return false;
|
|
@@ -79010,7 +79045,8 @@ async function authenticate(request, env2) {
|
|
|
79010
79045
|
user: {
|
|
79011
79046
|
id: "super_admin",
|
|
79012
79047
|
username: "admin",
|
|
79013
|
-
role: "admin"
|
|
79048
|
+
role: "admin",
|
|
79049
|
+
roles: []
|
|
79014
79050
|
},
|
|
79015
79051
|
authType: "super_admin"
|
|
79016
79052
|
};
|
|
@@ -79031,6 +79067,7 @@ async function authenticate(request, env2) {
|
|
|
79031
79067
|
username: user.username,
|
|
79032
79068
|
role: user.role,
|
|
79033
79069
|
permissions: parsePermissions(user.permissions),
|
|
79070
|
+
roles: user.roles ?? [],
|
|
79034
79071
|
platform_user_id: user.platform_user_id ?? null,
|
|
79035
79072
|
email: user.email ?? null,
|
|
79036
79073
|
display_name: user.display_name ?? null,
|
|
@@ -79054,6 +79091,7 @@ async function authenticate(request, env2) {
|
|
|
79054
79091
|
username: user.username,
|
|
79055
79092
|
role: user.role,
|
|
79056
79093
|
permissions: parsePermissions(user.permissions),
|
|
79094
|
+
roles: user.roles ?? [],
|
|
79057
79095
|
platform_user_id: user.platform_user_id ?? null,
|
|
79058
79096
|
email: user.email ?? null,
|
|
79059
79097
|
display_name: user.display_name ?? null,
|
|
@@ -79332,6 +79370,8 @@ function normalizeLocalBootstrap(payload, endpoint) {
|
|
|
79332
79370
|
id: platformUserId,
|
|
79333
79371
|
username,
|
|
79334
79372
|
role,
|
|
79373
|
+
roles: Array.isArray(payload.user?.roles) && payload.user.roles.every((role2) => typeof role2 === "string") ? payload.user.roles : [],
|
|
79374
|
+
roles_version: typeof payload.user?.roles_version === "number" ? payload.user.roles_version : 0,
|
|
79335
79375
|
email: typeof payload.user?.email === "string" ? payload.user.email : null,
|
|
79336
79376
|
display_name: typeof payload.user?.display_name === "string" ? payload.user.display_name : null,
|
|
79337
79377
|
avatar_url: typeof payload.user?.avatar_url === "string" ? payload.user.avatar_url : null,
|
|
@@ -79389,7 +79429,9 @@ async function upsertReplicaUserForPlatformProfile(env2, profile) {
|
|
|
79389
79429
|
email: profile.email ?? null,
|
|
79390
79430
|
avatar_url: profile.avatar_url ?? null,
|
|
79391
79431
|
role: profile.role ?? "admin",
|
|
79392
|
-
permissions: profile.permissions ?? null
|
|
79432
|
+
permissions: profile.permissions ?? null,
|
|
79433
|
+
roles: profile.roles ?? [],
|
|
79434
|
+
roles_version: profile.roles_version
|
|
79393
79435
|
});
|
|
79394
79436
|
}
|
|
79395
79437
|
async function mintLocalSessionForPlatformUser(env2, platformUser) {
|
|
@@ -79403,7 +79445,7 @@ async function mintLocalSessionForPlatformUser(env2, platformUser) {
|
|
|
79403
79445
|
const tokenHash = await hashToken(token);
|
|
79404
79446
|
const expiresAt = Math.floor(Date.now() / 1e3) + SESSION_TTL_SECONDS;
|
|
79405
79447
|
await agentBuilder.createSession({ user_id: user.id, token_hash: tokenHash, expires_at: expiresAt });
|
|
79406
|
-
return { token, user: { id: user.id, username: user.username, role: user.role } };
|
|
79448
|
+
return { token, user: { id: user.id, username: user.username, role: user.role, roles: user.roles ?? [] } };
|
|
79407
79449
|
}
|
|
79408
79450
|
async function consumePlatformHandoffJti(env2, jti, expiresAt) {
|
|
79409
79451
|
return agentBuilderAuthStub(env2).consumePlatformHandoffJti({
|
|
@@ -79431,7 +79473,9 @@ async function createPlatformLocalSession(request, env2) {
|
|
|
79431
79473
|
display_name: identity.user.display_name ?? null,
|
|
79432
79474
|
email: identity.user.email ?? null,
|
|
79433
79475
|
avatar_url: identity.user.avatar_url ?? null,
|
|
79434
|
-
role: identity.user.role
|
|
79476
|
+
role: identity.user.role,
|
|
79477
|
+
roles: identity.user.roles ?? [],
|
|
79478
|
+
roles_version: identity.user.roles_version
|
|
79435
79479
|
});
|
|
79436
79480
|
const token = generateUserToken();
|
|
79437
79481
|
const tokenHash = await hashToken(token);
|
|
@@ -79446,7 +79490,8 @@ async function createPlatformLocalSession(request, env2) {
|
|
|
79446
79490
|
user: {
|
|
79447
79491
|
id: user.id,
|
|
79448
79492
|
username: user.username,
|
|
79449
|
-
role: user.role
|
|
79493
|
+
role: user.role,
|
|
79494
|
+
roles: user.roles ?? []
|
|
79450
79495
|
},
|
|
79451
79496
|
authType: "platform_token",
|
|
79452
79497
|
platform: identity
|
|
@@ -79698,7 +79743,7 @@ var config_get_default = defineController2(async ({ config, env: env2, req }) =>
|
|
|
79698
79743
|
});
|
|
79699
79744
|
|
|
79700
79745
|
// src/version.ts
|
|
79701
|
-
var BUILDER_VERSION = "0.41.
|
|
79746
|
+
var BUILDER_VERSION = "0.41.17".length > 0 ? "0.41.17" : "dev";
|
|
79702
79747
|
|
|
79703
79748
|
// src/api/diagnostics.get.ts
|
|
79704
79749
|
init_LLMRequest();
|
|
@@ -82109,6 +82154,101 @@ function authRateLimitedResponse(result) {
|
|
|
82109
82154
|
);
|
|
82110
82155
|
}
|
|
82111
82156
|
|
|
82157
|
+
// src/utils/key-exchange.ts
|
|
82158
|
+
var HOST_LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
82159
|
+
function validHost(host) {
|
|
82160
|
+
return host.length <= 253 && host.split(".").length >= 2 && host.split(".").every((label) => HOST_LABEL.test(label));
|
|
82161
|
+
}
|
|
82162
|
+
function canonicalSourceOrigin(value) {
|
|
82163
|
+
if (typeof value !== "string" || value.length > 300) return null;
|
|
82164
|
+
let parsed;
|
|
82165
|
+
try {
|
|
82166
|
+
parsed = new URL(value);
|
|
82167
|
+
} catch {
|
|
82168
|
+
return null;
|
|
82169
|
+
}
|
|
82170
|
+
if (parsed.protocol !== "https:" || parsed.username || parsed.password || parsed.port || parsed.search || parsed.hash || parsed.pathname !== "/" && parsed.pathname !== "" || !validHost(parsed.hostname) || value.replace(/\/$/, "") !== parsed.origin) {
|
|
82171
|
+
return null;
|
|
82172
|
+
}
|
|
82173
|
+
return parsed.origin;
|
|
82174
|
+
}
|
|
82175
|
+
function isTrustedOrigin(origin, trustedOrigins) {
|
|
82176
|
+
const host = origin.slice("https://".length);
|
|
82177
|
+
return trustedOrigins.some((entry) => {
|
|
82178
|
+
const trusted = entry.slice("https://".length);
|
|
82179
|
+
return trusted.startsWith("*.") ? host.endsWith(trusted.slice(1)) && host.length > trusted.length - 1 : host === trusted;
|
|
82180
|
+
});
|
|
82181
|
+
}
|
|
82182
|
+
|
|
82183
|
+
// src/api/auth/exchange.post.ts
|
|
82184
|
+
var ADDRESS_LIMIT = { limit: 30, window_seconds: 60 * 60 };
|
|
82185
|
+
var SOURCE_TIMEOUT_MS = 5e3;
|
|
82186
|
+
function refused(status, error, message) {
|
|
82187
|
+
return Response.json({ error, message }, { status, headers: { "Cache-Control": "no-store" } });
|
|
82188
|
+
}
|
|
82189
|
+
var exchange_post_default = defineController2(async ({ req, env: env2, config }) => {
|
|
82190
|
+
const trustedOrigins = config?.keyExchange?.trustedOrigins;
|
|
82191
|
+
if (!trustedOrigins?.length) {
|
|
82192
|
+
return refused(404, "key_exchange_unsupported", "This instance does not exchange keys.");
|
|
82193
|
+
}
|
|
82194
|
+
const body = await req.json().catch(() => null);
|
|
82195
|
+
const sourceOrigin = canonicalSourceOrigin(body?.source_origin);
|
|
82196
|
+
const sourceKey = typeof body?.source_key === "string" ? body.source_key.trim() : "";
|
|
82197
|
+
if (!sourceOrigin || !sourceKey || sourceKey.length > 512) {
|
|
82198
|
+
return refused(400, "invalid_request", "source_origin and source_key are required.");
|
|
82199
|
+
}
|
|
82200
|
+
if (sourceOrigin === new URL(req.url).origin || !isTrustedOrigin(sourceOrigin, trustedOrigins)) {
|
|
82201
|
+
return refused(403, "untrusted_origin", "This instance does not trust that origin.");
|
|
82202
|
+
}
|
|
82203
|
+
const agentBuilder = env2.AGENT_BUILDER.get(env2.AGENT_BUILDER.idFromName("singleton"));
|
|
82204
|
+
const addressLimit = await agentBuilder.consumeAuthRateLimit({
|
|
82205
|
+
key: await authRateLimitKey("key-exchange-address", authClientAddress(req)),
|
|
82206
|
+
...ADDRESS_LIMIT
|
|
82207
|
+
});
|
|
82208
|
+
if (!addressLimit.allowed) return authRateLimitedResponse(addressLimit);
|
|
82209
|
+
let identity;
|
|
82210
|
+
try {
|
|
82211
|
+
const response = await fetch(`${sourceOrigin}/api/auth/me`, {
|
|
82212
|
+
headers: { Authorization: `Bearer ${sourceKey}`, Accept: "application/json" },
|
|
82213
|
+
redirect: "manual",
|
|
82214
|
+
signal: AbortSignal.timeout(SOURCE_TIMEOUT_MS)
|
|
82215
|
+
});
|
|
82216
|
+
if (response.status === 401 || response.status === 403) {
|
|
82217
|
+
return refused(401, "source_key_rejected", "The source deployment rejected the key.");
|
|
82218
|
+
}
|
|
82219
|
+
if (!response.ok) {
|
|
82220
|
+
return refused(502, "source_unavailable", `The source deployment answered ${response.status}.`);
|
|
82221
|
+
}
|
|
82222
|
+
identity = await response.json();
|
|
82223
|
+
} catch {
|
|
82224
|
+
return refused(502, "source_unavailable", "The source deployment could not be reached.");
|
|
82225
|
+
}
|
|
82226
|
+
if (identity?.authType !== "api_key") {
|
|
82227
|
+
return refused(401, "source_key_rejected", "Only API keys can be exchanged.");
|
|
82228
|
+
}
|
|
82229
|
+
const platformUserId = identity.user?.platform_user_id;
|
|
82230
|
+
if (typeof platformUserId !== "string" || !platformUserId) {
|
|
82231
|
+
return refused(403, "unknown_user", "The key does not belong to a platform user.");
|
|
82232
|
+
}
|
|
82233
|
+
const user = await agentBuilder.getUserByPlatformUserId(platformUserId);
|
|
82234
|
+
if (!user) {
|
|
82235
|
+
return refused(403, "unknown_user", "That user has not signed in to this instance.");
|
|
82236
|
+
}
|
|
82237
|
+
const token = generateApiKey();
|
|
82238
|
+
const sourceHost = new URL(sourceOrigin).hostname;
|
|
82239
|
+
await agentBuilder.createApiKey({
|
|
82240
|
+
name: `Key exchange from ${sourceHost}`.slice(0, 100),
|
|
82241
|
+
key_hash: await hashToken(token),
|
|
82242
|
+
key_prefix: getTokenPrefix(token),
|
|
82243
|
+
last_five: getLastChars(token, 5),
|
|
82244
|
+
user_id: user.id
|
|
82245
|
+
});
|
|
82246
|
+
return Response.json(
|
|
82247
|
+
{ token, endpoint: new URL(req.url).origin, user: { id: user.id, username: user.username } },
|
|
82248
|
+
{ status: 201, headers: { "Cache-Control": "no-store" } }
|
|
82249
|
+
);
|
|
82250
|
+
});
|
|
82251
|
+
|
|
82112
82252
|
// src/api/auth/login.post.ts
|
|
82113
82253
|
var LOGIN_ADDRESS_LIMIT = { limit: 10, window_seconds: 5 * 60 };
|
|
82114
82254
|
var LOGIN_IDENTITY_LIMIT = { limit: 25, window_seconds: 15 * 60 };
|
|
@@ -82371,6 +82511,7 @@ var platform_replica_post_default = defineController2(async ({ req, env: env2 })
|
|
|
82371
82511
|
const agentBuilder = env2.AGENT_BUILDER.get(env2.AGENT_BUILDER.idFromName("singleton"));
|
|
82372
82512
|
const result = await agentBuilder.applyPlatformReplicaSnapshot({
|
|
82373
82513
|
users: payload.users,
|
|
82514
|
+
role_revocations: payload.role_revocations,
|
|
82374
82515
|
api_keys: payload.api_keys ?? []
|
|
82375
82516
|
});
|
|
82376
82517
|
return Response.json({ ok: true, ...result });
|
|
@@ -86225,7 +86366,9 @@ var callback_get_default = defineController2(async ({ req, env: env2 }) => {
|
|
|
86225
86366
|
email: payload.email ?? null,
|
|
86226
86367
|
avatar_url: payload.avatar_url ?? null,
|
|
86227
86368
|
role: payload.role,
|
|
86228
|
-
permissions: payload.permissions ?? null
|
|
86369
|
+
permissions: payload.permissions ?? null,
|
|
86370
|
+
roles: payload.roles ?? [],
|
|
86371
|
+
roles_version: payload.roles_version
|
|
86229
86372
|
});
|
|
86230
86373
|
const returnTo = failReturnTo;
|
|
86231
86374
|
const headers = new Headers({
|
|
@@ -86679,7 +86822,9 @@ async function resolveDeviceApprovalIdentity(req, env2) {
|
|
|
86679
86822
|
email: payload.email ?? null,
|
|
86680
86823
|
avatar_url: payload.avatar_url ?? null,
|
|
86681
86824
|
role: payload.role,
|
|
86682
|
-
permissions: payload.permissions ?? null
|
|
86825
|
+
permissions: payload.permissions ?? null,
|
|
86826
|
+
roles: payload.roles ?? [],
|
|
86827
|
+
roles_version: payload.roles_version
|
|
86683
86828
|
};
|
|
86684
86829
|
return {
|
|
86685
86830
|
confirmationSubject: `platform:${payload.platform_user_id}`,
|
|
@@ -88079,6 +88224,7 @@ var routeHandlers = {
|
|
|
88079
88224
|
"POST:/auth/brolly-control": brolly_control_post_default,
|
|
88080
88225
|
"GET:/auth/config": config_get_default2,
|
|
88081
88226
|
"DELETE:/auth/current-key": current_key_delete_default,
|
|
88227
|
+
"POST:/auth/exchange": exchange_post_default,
|
|
88082
88228
|
"POST:/auth/login": login_post_default,
|
|
88083
88229
|
"POST:/auth/logout": logout_post_default,
|
|
88084
88230
|
"GET:/auth/me": me_get_default,
|