@standardagents/builder 0.41.16 → 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.
@@ -1,4 +1,4 @@
1
- import { i as AuthContext, b as ThreadEnv, v as Agent, x as ThreadMetadata, z as ToolResult, M as Message, n as ClientToolRequest, o as ClientToolResponse, V as ProxyStreamReceiver, W as ProxyStreamFrame, p as ClientStreamRequest, X as ProxyStreamTarget, q as ClientStreamResponse, Y as ProxyStreamOpenResult, H as FileRecord, Z as SkillStorageScope, F as FlowState, N as FileStats, K as GrepResult, J as AttachmentRef, U as MessageContent, G as Env, w as ThreadInstance } from './index-BrQgCoFh.js';
1
+ import { i as AuthContext, b as ThreadEnv, v as Agent, x as ThreadMetadata, z as ToolResult, M as Message, n as ClientToolRequest, o as ClientToolResponse, V as ProxyStreamReceiver, W as ProxyStreamFrame, p as ClientStreamRequest, X as ProxyStreamTarget, q as ClientStreamResponse, Y as ProxyStreamOpenResult, H as FileRecord, Z as SkillStorageScope, F as FlowState, N as FileStats, K as GrepResult, J as AttachmentRef, U as MessageContent, G as Env, w as ThreadInstance } from './index-C82dLGPq.js';
2
2
  import { DurableObject, WorkerEntrypoint } from 'cloudflare:workers';
3
3
  import { CodeExecutionOptions, CodeExecutionResult, SubagentRegistryEntry, InjectMessageInput, QueueMessageInput, UserRoomConnection, CredentialGrant, SkillMetadata, SkillFileInput, ModelDefinition as ModelDefinition$1, ToolArgs, PromptTextPart, PromptEnvPart, VariableDefinition, SubpromptConfig as SubpromptConfig$1, PromptToolConfig as PromptToolConfig$1, ReasoningConfig, HumanSide as HumanSide$1, SubagentRelationship as SubagentRelationship$1, ParentHookRequirement, LLMProviderInterface, ContentPart, TextPart, ImagePart, FilePart, ThreadState, NamespaceContext, DefinitionLoader } from '@standardagents/spec';
4
4
  import { N as NamespacedRegistry } from './types-Dhd0M369.js';
@@ -2150,6 +2150,8 @@ interface UpdateThreadParams {
2150
2150
  */
2151
2151
  type InstanceRole = 'admin' | 'user' | 'api';
2152
2152
  interface User {
2153
+ /** Platform-owned opaque application roles; unrelated to instance permissions. */
2154
+ roles?: string[];
2153
2155
  id: string;
2154
2156
  username: string;
2155
2157
  password_hash: string;
@@ -2166,6 +2168,8 @@ interface User {
2166
2168
  updated_at: number;
2167
2169
  }
2168
2170
  interface PlatformReplicaUser {
2171
+ roles?: string[];
2172
+ roles_version?: number;
2169
2173
  platform_user_id: string;
2170
2174
  username?: string | null;
2171
2175
  email?: string | null;
@@ -2186,6 +2190,10 @@ interface PlatformReplicaApiKey {
2186
2190
  created_at?: number | null;
2187
2191
  }
2188
2192
  interface PlatformReplicaSnapshot {
2193
+ role_revocations?: Array<{
2194
+ platform_user_id: string;
2195
+ roles_version: number;
2196
+ }>;
2189
2197
  users: PlatformReplicaUser[];
2190
2198
  api_keys?: PlatformReplicaApiKey[];
2191
2199
  }
@@ -2683,9 +2691,9 @@ declare class DurableAgentBuilder<Env extends AgentBuilderEnv = AgentBuilderEnv>
2683
2691
  * Delete a user.
2684
2692
  */
2685
2693
  deleteUser(id: string): Promise<boolean>;
2686
- /**
2687
- * Upsert a platform-replicated identity and return the local user row.
2688
- */
2694
+ /** Apply an authoritative role replacement while retaining revocation fences. */
2695
+ private applyApplicationRoles;
2696
+ /** Upsert a platform-replicated identity and return the local user row. */
2689
2697
  upsertPlatformReplicaUser(replica: PlatformReplicaUser): Promise<User>;
2690
2698
  /**
2691
2699
  * Apply a full platform read-replica snapshot for this instance.
package/dist/runtime.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { m as AgentBuilderEnv, n as AgentBuilderEvent, A as AgentDefinition, ah as BroadcastOptions, C as CodeExecutionBridge, h as DurableAgentBuilder, D as DurableThread, l as DurableUserHub, af as FlowStateSdk, ai as FlowStateWithSdk, G as HandlerSide, H as HubClientInfo, E as HumanSide, aq as ImageContextConfig, ae as InjectMessageOptions, as as LLMProviderInterface, M as ModelDefinition, aL as NamespaceResolutionError, w as PromptContent, s as PromptDefinition, y as PromptIncludePart, x as PromptPart, F as PromptSide, t as PromptToolConfig, P as Provider, at as ProviderContentPart, aw as ProviderFilePart, av as ProviderImagePart, ar as ProviderRegistry, au as ProviderTextPart, B as SessionToolBinding, z as SessionToolConfig, I as SideConfig, J as SubagentRelationship, u as SubagentToolConfig, S as SubpromptConfig, o as ThreadEventPayload, p as ThreadRegistryEntry, T as ThreadWatchdog, j as ThreadWatchdogState, v as ToolConfig, U as UpdateThreadParams, q as User, k as WatchdogCheckin, W as WatchdogProbeResult, f as applyRuntimeCors, am as buildImageDescription, c as canAccessThread, a9 as cat, aJ as createNamespaceContext, Q as emitThreadEvent, ag as enhanceFlowState, a0 as exists, ad as find, R as forceTurn, ap as generateImageDescription, a7 as getFileStats, N as getMessages, al as getMessagesToSummarize, az as getShortName, a8 as getThumbnail, ak as getUnsummarizedImageAttachments, aG as getVisibleAgentNames, aI as getVisibleModelNames, aH as getVisiblePromptNames, aF as getVisibleToolNames, ac as grep, aj as hasImageAttachments, aa as head, L as injectMessage, d as isAdminOnlyApiRoute, i as isHostedInstance, b as isPublicApiRoute, aK as isQualifiedName, e as isSameOriginBrowserRequest, a as isTrustedLocalDevelopmentRequest, Z as linkFile, a2 as mkdir, a5 as move, ao as optimizeImageContext, ax as parseQualifiedName, ay as qualifyName, K as queueTool, _ as readFile, a3 as readdir, O as reloadHistory, a6 as rename, an as replaceImagesWithDescriptions, aD as resolveAgent, aE as resolveHook, aC as resolveModel, aB as resolvePrompt, aA as resolveTool, a4 as rmdir, r as runtimeCorsHeaders, g as runtimePreflightResponse, $ as stat, ab as tail, a1 as unlink, V as updateThread, X as writeFile, Y as writeImage } from './resolver-CWWRzZU1.js';
2
- export { v as Agent, J as AttachmentRef, i as AuthContext, A as AuthUser, e as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, t as ClientDuplex, u as ClientForwarding, p as ClientStreamRequest, q as ClientStreamResponse, n as ClientToolRequest, o as ClientToolResponse, B as Controller, a as ControllerContext, G as Env, H as FileRecord, N as FileStats, D as FlowResult, F as FlowState, K as GrepResult, P as ImageContentPart, I as ImageMetadata, L as LLMResponse, M as Message, U as MessageContent, Q as MultimodalContent, R as RequestContext, S as StorageBackend, E as TelemetryEvent, O as TextContentPart, T as ThreadEndpointContext, b as ThreadEnv, w as ThreadInstance, x as ThreadMetadata, y as ToolCall, z as ToolResult, f as authenticate, j as callClient, k as callClientStream, c as createThreadEndpointHandler, m as decodeStreamChunk, d as defineController, l as encodeStreamChunk, h as endpointCallerFromAuth, g as requireAdmin, r as requireAuth, s as supportsClientForwarding } from './index-BrQgCoFh.js';
1
+ export { m as AgentBuilderEnv, n as AgentBuilderEvent, A as AgentDefinition, ah as BroadcastOptions, C as CodeExecutionBridge, h as DurableAgentBuilder, D as DurableThread, l as DurableUserHub, af as FlowStateSdk, ai as FlowStateWithSdk, G as HandlerSide, H as HubClientInfo, E as HumanSide, aq as ImageContextConfig, ae as InjectMessageOptions, as as LLMProviderInterface, M as ModelDefinition, aL as NamespaceResolutionError, w as PromptContent, s as PromptDefinition, y as PromptIncludePart, x as PromptPart, F as PromptSide, t as PromptToolConfig, P as Provider, at as ProviderContentPart, aw as ProviderFilePart, av as ProviderImagePart, ar as ProviderRegistry, au as ProviderTextPart, B as SessionToolBinding, z as SessionToolConfig, I as SideConfig, J as SubagentRelationship, u as SubagentToolConfig, S as SubpromptConfig, o as ThreadEventPayload, p as ThreadRegistryEntry, T as ThreadWatchdog, j as ThreadWatchdogState, v as ToolConfig, U as UpdateThreadParams, q as User, k as WatchdogCheckin, W as WatchdogProbeResult, f as applyRuntimeCors, am as buildImageDescription, c as canAccessThread, a9 as cat, aJ as createNamespaceContext, Q as emitThreadEvent, ag as enhanceFlowState, a0 as exists, ad as find, R as forceTurn, ap as generateImageDescription, a7 as getFileStats, N as getMessages, al as getMessagesToSummarize, az as getShortName, a8 as getThumbnail, ak as getUnsummarizedImageAttachments, aG as getVisibleAgentNames, aI as getVisibleModelNames, aH as getVisiblePromptNames, aF as getVisibleToolNames, ac as grep, aj as hasImageAttachments, aa as head, L as injectMessage, d as isAdminOnlyApiRoute, i as isHostedInstance, b as isPublicApiRoute, aK as isQualifiedName, e as isSameOriginBrowserRequest, a as isTrustedLocalDevelopmentRequest, Z as linkFile, a2 as mkdir, a5 as move, ao as optimizeImageContext, ax as parseQualifiedName, ay as qualifyName, K as queueTool, _ as readFile, a3 as readdir, O as reloadHistory, a6 as rename, an as replaceImagesWithDescriptions, aD as resolveAgent, aE as resolveHook, aC as resolveModel, aB as resolvePrompt, aA as resolveTool, a4 as rmdir, r as runtimeCorsHeaders, g as runtimePreflightResponse, $ as stat, ab as tail, a1 as unlink, V as updateThread, X as writeFile, Y as writeImage } from './resolver-eygn_O1w.js';
2
+ export { v as Agent, J as AttachmentRef, i as AuthContext, A as AuthUser, e as BuilderThreadEndpointHandler, C as CLIENT_STREAM_CHUNK_BYTES, t as ClientDuplex, u as ClientForwarding, p as ClientStreamRequest, q as ClientStreamResponse, n as ClientToolRequest, o as ClientToolResponse, B as Controller, a as ControllerContext, G as Env, H as FileRecord, N as FileStats, D as FlowResult, F as FlowState, K as GrepResult, P as ImageContentPart, I as ImageMetadata, L as LLMResponse, M as Message, U as MessageContent, Q as MultimodalContent, R as RequestContext, S as StorageBackend, E as TelemetryEvent, O as TextContentPart, T as ThreadEndpointContext, b as ThreadEnv, w as ThreadInstance, x as ThreadMetadata, y as ToolCall, z as ToolResult, f as authenticate, j as callClient, k as callClientStream, c as createThreadEndpointHandler, m as decodeStreamChunk, d as defineController, l as encodeStreamChunk, h as endpointCallerFromAuth, g as requireAdmin, r as requireAuth, s as supportsClientForwarding } from './index-C82dLGPq.js';
3
3
  export { AgentType, DefineHandlerOptions, DefinitionLoader, GlobalNamespaceContext, HANDLER_SYMBOL, HandlerDefinition, HookExecutionContext, HookExecutionSource, HookSignatures, ImageContent, ModelCapabilities, ModelProvider, NamespaceContext, PackageSignature, PackedExports, PackedMeta, PackedMetadata, PackedNamespaceContext, ParentHookRequirement, ParentHookStage, PromptInput, PromptTextPart, ProviderAssistantMessage, ProviderError, ProviderErrorCode, ProviderFactory, ProviderFactoryConfig, ProviderFinishReason, ProviderGeneratedImage, ProviderMessage, ProviderMessageContent, ModelCapabilities as ProviderModelCapabilities, ProviderReasoningDetail, ProviderRequest, ProviderResponse, ProviderStreamChunk, ProviderSystemMessage, ProviderTool, ProviderToolCallPart, ProviderToolMessage, ProviderToolResultContent, ProviderUsage, ProviderUserMessage, ReasoningConfig, StructuredPrompt, TextContent, ThreadHookName, Tool, ToolArgs, ToolArgsNode, ToolArgsRawShape, ToolContent, belongsToPackage, defineAgent, defineHandler, defineHook, defineModel, definePrompt, defineProvider, defineTool, isHandler, isPacked, isVisibleInNamespace, mapReasoningLevel, providerConst, providerEnv, providerValue } from '@standardagents/spec';
4
4
  export { N as NamespacedRegistry } from './types-Dhd0M369.js';
5
5
  import 'cloudflare:workers';
package/dist/runtime.js CHANGED
@@ -10322,6 +10322,24 @@ var init_platform_handoff_jtis = __esm({
10322
10322
  }
10323
10323
  });
10324
10324
 
10325
+ // src/durable-objects/agentbuilder-migrations/0022_application_roles.ts
10326
+ var migration60;
10327
+ var init_application_roles = __esm({
10328
+ "src/durable-objects/agentbuilder-migrations/0022_application_roles.ts"() {
10329
+ migration60 = {
10330
+ version: 22,
10331
+ async up(sql) {
10332
+ sql.exec(`CREATE TABLE platform_application_roles (
10333
+ platform_user_id TEXT PRIMARY KEY,
10334
+ roles TEXT NOT NULL DEFAULT '[]',
10335
+ roles_version INTEGER NOT NULL DEFAULT 0
10336
+ )`);
10337
+ sql.exec(`INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '22')`);
10338
+ }
10339
+ };
10340
+ }
10341
+ });
10342
+
10325
10343
  // src/durable-objects/agentbuilder-migrations/index.ts
10326
10344
  var migrations2, LATEST_SCHEMA_VERSION2;
10327
10345
  var init_agentbuilder_migrations = __esm({
@@ -10347,9 +10365,10 @@ var init_agentbuilder_migrations = __esm({
10347
10365
  init_scope_skills();
10348
10366
  init_websocket_tickets();
10349
10367
  init_platform_handoff_jtis();
10350
- migrations2 = [migration39, migration40, migration41, migration42, migration43, migration44, migration45, migration46, migration47, migration48, migration49, migration50, migration51, migration52, migration53, migration54, migration55, migration56, migration57, migration58, migration59];
10368
+ init_application_roles();
10369
+ migrations2 = [migration39, migration40, migration41, migration42, migration43, migration44, migration45, migration46, migration47, migration48, migration49, migration50, migration51, migration52, migration53, migration54, migration55, migration56, migration57, migration58, migration59, migration60];
10351
10370
  LATEST_SCHEMA_VERSION2 = migrations2.reduce(
10352
- (max, migration60) => Math.max(max, migration60.version),
10371
+ (max, migration61) => Math.max(max, migration61.version),
10353
10372
  0
10354
10373
  );
10355
10374
  }
@@ -11158,9 +11177,9 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
11158
11177
  }
11159
11178
  }
11160
11179
  async runMigrations(fromVersion) {
11161
- for (const migration60 of migrations2) {
11162
- if (migration60.version > fromVersion) {
11163
- await migration60.up(this.ctx.storage.sql);
11180
+ for (const migration61 of migrations2) {
11181
+ if (migration61.version > fromVersion) {
11182
+ await migration61.up(this.ctx.storage.sql);
11164
11183
  }
11165
11184
  }
11166
11185
  }
@@ -12715,6 +12734,7 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
12715
12734
  // admin meaning.
12716
12735
  role: row.role === "user" ? "user" : row.role === "api" ? "api" : "admin",
12717
12736
  permissions: parseStoredPermissions(row.permissions),
12737
+ roles: parseStoredPermissions(row.roles) ?? [],
12718
12738
  platform_user_id: row.platform_user_id ?? null,
12719
12739
  email: row.email ?? null,
12720
12740
  display_name: row.display_name ?? null,
@@ -12732,7 +12752,8 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
12732
12752
  await this.ensureMigrated();
12733
12753
  const cursor = await this.ctx.storage.sql.exec(
12734
12754
  `SELECT id, username, password_hash, COALESCE(instance_role, role) AS role,
12735
- permissions, platform_user_id, email, display_name, avatar_url, source, replica_active,
12755
+ permissions, (SELECT roles FROM platform_application_roles WHERE platform_user_id = users.platform_user_id) AS roles,
12756
+ platform_user_id, email, display_name, avatar_url, source, replica_active,
12736
12757
  created_at, updated_at
12737
12758
  FROM users WHERE username = ? AND deleted_at IS NULL AND replica_active != 0`,
12738
12759
  username
@@ -12748,7 +12769,8 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
12748
12769
  await this.ensureMigrated();
12749
12770
  const cursor = await this.ctx.storage.sql.exec(
12750
12771
  `SELECT id, username, password_hash, COALESCE(instance_role, role) AS role,
12751
- permissions, platform_user_id, email, display_name, avatar_url, source, replica_active,
12772
+ permissions, (SELECT roles FROM platform_application_roles WHERE platform_user_id = users.platform_user_id) AS roles,
12773
+ platform_user_id, email, display_name, avatar_url, source, replica_active,
12752
12774
  created_at, updated_at
12753
12775
  FROM users WHERE id = ? AND deleted_at IS NULL AND replica_active != 0`,
12754
12776
  id
@@ -12792,6 +12814,7 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
12792
12814
  password_hash: params.password_hash,
12793
12815
  role: params.role || "admin",
12794
12816
  permissions: params.permissions ?? null,
12817
+ roles: [],
12795
12818
  platform_user_id: params.platform_user_id ?? null,
12796
12819
  email: params.email ?? null,
12797
12820
  display_name: params.display_name ?? null,
@@ -12925,11 +12948,31 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
12925
12948
  );
12926
12949
  return true;
12927
12950
  }
12928
- /**
12929
- * Upsert a platform-replicated identity and return the local user row.
12930
- */
12951
+ /** Apply an authoritative role replacement while retaining revocation fences. */
12952
+ applyApplicationRoles(platformUserId, roles, version, revoke = false) {
12953
+ const revision = version === void 0 ? 0 : version;
12954
+ if (typeof revision !== "number" || !Number.isSafeInteger(revision) || revision < 0) {
12955
+ throw new Error("Invalid application roles revision");
12956
+ }
12957
+ if (roles !== void 0 && (!Array.isArray(roles) || !roles.every((role) => typeof role === "string"))) {
12958
+ throw new Error("Invalid application roles");
12959
+ }
12960
+ this.ctx.storage.sql.exec(
12961
+ `INSERT INTO platform_application_roles (platform_user_id, roles, roles_version)
12962
+ VALUES (?, ?, ?)
12963
+ ON CONFLICT(platform_user_id) DO UPDATE SET roles = excluded.roles, roles_version = excluded.roles_version
12964
+ WHERE excluded.roles_version > platform_application_roles.roles_version
12965
+ OR (? = 1 AND excluded.roles_version = platform_application_roles.roles_version)`,
12966
+ platformUserId,
12967
+ JSON.stringify(roles ?? []),
12968
+ revision,
12969
+ revoke ? 1 : 0
12970
+ );
12971
+ }
12972
+ /** Upsert a platform-replicated identity and return the local user row. */
12931
12973
  async upsertPlatformReplicaUser(replica) {
12932
12974
  await this.ensureMigrated();
12975
+ this.applyApplicationRoles(replica.platform_user_id, replica.roles, replica.roles_version);
12933
12976
  const now = Math.floor(Date.now() / 1e3);
12934
12977
  const fallback = this.normalizeReplicaUsername(
12935
12978
  replica.email?.split("@")[0] ?? null,
@@ -12976,7 +13019,7 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
12976
13019
  }
12977
13020
  return updated;
12978
13021
  }
12979
- return this.createUser({
13022
+ const created = await this.createUser({
12980
13023
  username: availableUsername,
12981
13024
  password_hash: `platform-replica:${crypto.randomUUID()}`,
12982
13025
  role: replica.role,
@@ -12987,12 +13030,18 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
12987
13030
  avatar_url: replica.avatar_url ?? null,
12988
13031
  source: "standard_agents"
12989
13032
  });
13033
+ const user = await this.getUserById(created.id);
13034
+ if (!user) throw new Error("Failed to load replicated user after creation");
13035
+ return user;
12990
13036
  }
12991
13037
  /**
12992
13038
  * Apply a full platform read-replica snapshot for this instance.
12993
13039
  */
12994
13040
  async applyPlatformReplicaSnapshot(snapshot) {
12995
13041
  await this.ensureMigrated();
13042
+ for (const revocation of snapshot.role_revocations ?? []) {
13043
+ this.applyApplicationRoles(revocation.platform_user_id, [], revocation.roles_version, true);
13044
+ }
12996
13045
  const activeUserIds = /* @__PURE__ */ new Set();
12997
13046
  for (const replicaUser of snapshot.users) {
12998
13047
  const user = await this.upsertPlatformReplicaUser(replicaUser);
@@ -13045,10 +13094,9 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
13045
13094
  const keys = snapshot.api_keys ?? [];
13046
13095
  for (const key of keys) {
13047
13096
  const user = key.user_platform_id ? await this.getUserByPlatformUserId(key.user_platform_id) : await this.getFirstReplicaAdminUser();
13048
- const keyUser = user ?? await this.getFirstReplicaAdminUser();
13049
- if (!keyUser) continue;
13097
+ if (!user) continue;
13050
13098
  activePlatformKeyIds.add(key.id);
13051
- await this.upsertPlatformReplicaApiKey(key, keyUser.id);
13099
+ await this.upsertPlatformReplicaApiKey(key, user.id);
13052
13100
  }
13053
13101
  const now = Math.floor(Date.now() / 1e3);
13054
13102
  if (activePlatformKeyIds.size > 0) {
@@ -17660,9 +17708,9 @@ var init_DurableThread = __esm({
17660
17708
  * Each migration is run in order, starting from the current version + 1.
17661
17709
  */
17662
17710
  async runMigrations(fromVersion) {
17663
- for (const migration60 of migrations) {
17664
- if (migration60.version > fromVersion) {
17665
- await migration60.up(this.ctx.storage.sql);
17711
+ for (const migration61 of migrations) {
17712
+ if (migration61.version > fromVersion) {
17713
+ await migration61.up(this.ctx.storage.sql);
17666
17714
  }
17667
17715
  }
17668
17716
  }
@@ -29540,6 +29588,7 @@ var init_ThreadStateImpl = __esm({
29540
29588
  username: user.username,
29541
29589
  role: user.role,
29542
29590
  permissions: user.permissions ?? null,
29591
+ roles: user.roles ?? [],
29543
29592
  email: user.email ?? null,
29544
29593
  display_name: user.display_name ?? null,
29545
29594
  avatar_url: user.avatar_url ?? null
@@ -29942,12 +29991,13 @@ function runtimePreflightResponse(request, env) {
29942
29991
  // src/middleware/auth.ts
29943
29992
  function endpointCallerFromAuth(auth) {
29944
29993
  if (!auth) return null;
29945
- const { id, username, role, permissions, email, display_name, avatar_url } = auth.user;
29994
+ const { id, username, role, permissions, roles, email, display_name, avatar_url } = auth.user;
29946
29995
  return {
29947
29996
  id,
29948
29997
  username,
29949
29998
  role,
29950
29999
  permissions: permissions ?? null,
30000
+ roles: roles ?? [],
29951
30001
  email: email ?? null,
29952
30002
  display_name: display_name ?? null,
29953
30003
  avatar_url: avatar_url ?? null
@@ -29993,6 +30043,8 @@ function parseWebSocketTicketAuth(authJson) {
29993
30043
  if (typeof user.id !== "string" || typeof user.username !== "string" || typeof user.role !== "string" || record.authType !== "super_admin" && record.authType !== "session" && record.authType !== "api_key") {
29994
30044
  return null;
29995
30045
  }
30046
+ const roles = user.roles;
30047
+ if (roles !== void 0 && (!Array.isArray(roles) || !roles.every((role) => typeof role === "string"))) return null;
29996
30048
  const permissions = user.permissions;
29997
30049
  if (permissions !== void 0 && permissions !== null && (!Array.isArray(permissions) || !permissions.every((permission) => typeof permission === "string"))) {
29998
30050
  return null;
@@ -30004,6 +30056,7 @@ function parseWebSocketTicketAuth(authJson) {
30004
30056
  username: user.username,
30005
30057
  role: user.role,
30006
30058
  permissions,
30059
+ roles: Array.isArray(roles) ? roles : [],
30007
30060
  platform_user_id: typeof user.platform_user_id === "string" ? user.platform_user_id : null,
30008
30061
  email: typeof user.email === "string" ? user.email : null,
30009
30062
  display_name: typeof user.display_name === "string" ? user.display_name : null,
@@ -30027,7 +30080,19 @@ async function consumeWebSocketTicket(request, env) {
30027
30080
  ticket_hash: await hashToken(ticket),
30028
30081
  pathname: url.pathname
30029
30082
  });
30030
- return typeof authJson === "string" ? parseWebSocketTicketAuth(authJson) : null;
30083
+ const context = typeof authJson === "string" ? parseWebSocketTicketAuth(authJson) : null;
30084
+ if (!context || context.authType === "super_admin") return context;
30085
+ const user = await getAgentBuilder(env).getUserById(context.user.id);
30086
+ if (!user) return null;
30087
+ return {
30088
+ ...context,
30089
+ user: {
30090
+ ...context.user,
30091
+ role: user.role,
30092
+ permissions: parsePermissions(user.permissions),
30093
+ roles: user.roles ?? []
30094
+ }
30095
+ };
30031
30096
  }
30032
30097
  async function authenticate(request, env) {
30033
30098
  const ticketAuth = await consumeWebSocketTicket(request, env);
@@ -30050,7 +30115,8 @@ async function authenticate(request, env) {
30050
30115
  user: {
30051
30116
  id: "super_admin",
30052
30117
  username: "admin",
30053
- role: "admin"
30118
+ role: "admin",
30119
+ roles: []
30054
30120
  },
30055
30121
  authType: "super_admin"
30056
30122
  };
@@ -30071,6 +30137,7 @@ async function authenticate(request, env) {
30071
30137
  username: user.username,
30072
30138
  role: user.role,
30073
30139
  permissions: parsePermissions(user.permissions),
30140
+ roles: user.roles ?? [],
30074
30141
  platform_user_id: user.platform_user_id ?? null,
30075
30142
  email: user.email ?? null,
30076
30143
  display_name: user.display_name ?? null,
@@ -30094,6 +30161,7 @@ async function authenticate(request, env) {
30094
30161
  username: user.username,
30095
30162
  role: user.role,
30096
30163
  permissions: parsePermissions(user.permissions),
30164
+ roles: user.roles ?? [],
30097
30165
  platform_user_id: user.platform_user_id ?? null,
30098
30166
  email: user.email ?? null,
30099
30167
  display_name: user.display_name ?? null,
@@ -30531,6 +30599,7 @@ var UserStateImpl = class {
30531
30599
  username: user.username,
30532
30600
  role: user.role,
30533
30601
  permissions: user.permissions ?? null,
30602
+ roles: user.roles ?? [],
30534
30603
  email: user.email ?? null,
30535
30604
  display_name: user.display_name ?? null,
30536
30605
  avatar_url: user.avatar_url ?? null