@elevasis/core 0.48.0 → 0.49.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,52 @@
1
1
  import type { SupabaseClient, Json } from '../../../supabase'
2
- import type { ExecutionContext } from '../../../execution/engine/base/types'
3
- import type { AgentDefinition } from '../../../execution/engine/agent/core/types'
4
- import type { AgentMemory } from '../../../execution/engine/agent/memory/types'
5
- import type { SessionRow, SessionTurnResult } from '../types'
6
- import { createLLMAdapter } from '../../../execution/engine/llm/adapters/server/adapter-factory'
7
-
8
- export class Session {
2
+ import type { ExecutionContext } from '../../../execution/engine/base/types'
3
+ import type { AgentDefinition } from '../../../execution/engine/agent/core/types'
4
+ import type { AgentMemory } from '../../../execution/engine/agent/memory/types'
5
+ import type { SessionRow, SessionTurnResult } from '../types'
6
+ import { createLLMAdapter } from '../../../execution/engine/llm/adapters/server/adapter-factory'
7
+
8
+ export interface SessionTurnExecutorResult<TOutput> {
9
+ output: TOutput | null
10
+ memorySnapshot: AgentMemory
11
+ }
12
+
13
+ export type SessionTurnExecutor<TOutput> = (
14
+ session: Session,
15
+ lockedTurnNumber: number
16
+ ) => Promise<SessionTurnExecutorResult<TOutput>>
17
+
18
+ export interface SessionTurnExecutionOptions {
19
+ beforeExecute?: (session: Session, lockedTurnNumber: number) => Promise<void>
20
+ }
21
+
22
+ function isMemoryEntry(value: unknown): value is AgentMemory['history'][number] {
23
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false
24
+ const entry = value as Record<string, unknown>
25
+ return (
26
+ typeof entry.type === 'string' &&
27
+ typeof entry.content === 'string' &&
28
+ typeof entry.timestamp === 'number' &&
29
+ (typeof entry.turnNumber === 'number' || entry.turnNumber === null) &&
30
+ (typeof entry.iterationNumber === 'number' || entry.iterationNumber === null)
31
+ )
32
+ }
33
+
34
+ function isAgentMemory(value: unknown): value is AgentMemory {
35
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false
36
+ const memory = value as Record<string, unknown>
37
+ const sessionMemory = memory.sessionMemory
38
+ const history = memory.history
39
+ return (
40
+ !!sessionMemory &&
41
+ typeof sessionMemory === 'object' &&
42
+ !Array.isArray(sessionMemory) &&
43
+ Object.values(sessionMemory as Record<string, unknown>).every(isMemoryEntry) &&
44
+ Array.isArray(history) &&
45
+ history.every(isMemoryEntry)
46
+ )
47
+ }
48
+
49
+ export class Session {
9
50
  constructor(
10
51
  private db: SupabaseClient,
11
52
  private data: SessionRow
@@ -73,14 +114,45 @@ export class Session {
73
114
  * @param context - Full execution context (including sessionTurnMessages if streaming)
74
115
  * @returns Turn result with output and metadata
75
116
  */
76
- async executeTurn<TInput, TOutput>(
77
- agentDefinition: AgentDefinition,
78
- input: TInput,
79
- context: ExecutionContext
80
- ): Promise<SessionTurnResult<TOutput>> {
81
- const turnStartTime = Date.now()
82
-
83
- // NOTE: Using RPC to acquire row-level lock and get fresh state
117
+ async executeTurn<TInput, TOutput>(
118
+ agentDefinition: AgentDefinition,
119
+ input: TInput,
120
+ context: ExecutionContext,
121
+ options?: SessionTurnExecutionOptions
122
+ ): Promise<SessionTurnResult<TOutput>> {
123
+ return this.executeTurnWithExecutor(context, async () => {
124
+ // Create agent instance (stateless, recreated per turn)
125
+ const { Agent } = await import('../../../execution/engine/agent/core/agent')
126
+ const agent = new Agent<TInput, TOutput>(agentDefinition, createLLMAdapter)
127
+
128
+ // Execute agent (preloadMemory callback will restore session memory)
129
+ const output = await agent.execute(input, context)
130
+
131
+ // Update state and persist
132
+ const memorySnapshot = agent.getMemorySnapshot()
133
+ if (!memorySnapshot) {
134
+ throw new Error('Agent did not produce memory snapshot')
135
+ }
136
+
137
+ return { output, memorySnapshot }
138
+ }, options)
139
+ }
140
+
141
+ /**
142
+ * Execute a session turn with a caller-provided execution body.
143
+ *
144
+ * Keeps the session lifecycle centralized for both in-process agents and
145
+ * worker-backed external agents: acquire lock, validate active session,
146
+ * execute, persist memory snapshot, and increment turn count exactly once.
147
+ */
148
+ async executeTurnWithExecutor<TOutput>(
149
+ context: ExecutionContext,
150
+ executor: SessionTurnExecutor<TOutput>,
151
+ options?: SessionTurnExecutionOptions
152
+ ): Promise<SessionTurnResult<TOutput>> {
153
+ const turnStartTime = Date.now()
154
+
155
+ // NOTE: Using RPC to acquire row-level lock and get fresh state
84
156
  // This ensures atomic lock acquisition for concurrent turn prevention
85
157
  const { data, error } = await this.db.rpc('execute_session_turn', {
86
158
  p_session_id: this.sessionId
@@ -99,34 +171,31 @@ export class Session {
99
171
  this.data = lockResult as SessionRow
100
172
 
101
173
  // Validate
102
- if (this.isEnded) {
103
- throw new Error('Cannot execute turn on ended session')
104
- }
105
-
106
- // Create agent instance (stateless, recreated per turn)
107
- const { Agent } = await import('../../../execution/engine/agent/core/agent')
108
- const agent = new Agent<TInput, TOutput>(agentDefinition, createLLMAdapter)
109
-
110
- // Execute agent (preloadMemory callback will restore session memory)
111
- const output = await agent.execute(input, context)
112
-
113
- // Update state and persist
114
- const snapshot = agent.getMemorySnapshot()
115
- if (!snapshot) {
116
- throw new Error('Agent did not produce memory snapshot')
117
- }
118
-
119
- // Complete turn (messages already persisted immediately via onMessageEvent)
120
- await this.completeTurn(snapshot)
121
-
122
- return {
123
- sessionId: this.sessionId,
124
- executionId: context.executionId,
125
- turnNumber: this.data.session_total_turns ?? 0,
126
- output,
127
- duration: Date.now() - turnStartTime
128
- }
129
- }
174
+ if (this.isEnded) {
175
+ throw new Error('Cannot execute turn on ended session')
176
+ }
177
+
178
+ const lockedTurnNumber = (this.data.session_total_turns ?? 0) + 1
179
+ context.sessionTurnNumber = lockedTurnNumber
180
+ await options?.beforeExecute?.(this, lockedTurnNumber)
181
+
182
+ const result = await executor(this, lockedTurnNumber)
183
+ if (!isAgentMemory(result.memorySnapshot)) {
184
+ throw new Error('Session turn did not produce memory snapshot')
185
+ }
186
+
187
+ // Complete turn (messages already persisted immediately via onMessageEvent)
188
+ await this.completeTurn(result.memorySnapshot)
189
+
190
+ return {
191
+ sessionId: this.sessionId,
192
+ executionId: context.executionId,
193
+ lockedTurnNumber,
194
+ turnNumber: this.data.session_total_turns ?? 0,
195
+ output: result.output,
196
+ duration: Date.now() - turnStartTime
197
+ }
198
+ }
130
199
 
131
200
  /**
132
201
  * End this session (marks as ended, prevents future turns)
@@ -43,13 +43,15 @@ export interface ChatMessage {
43
43
  createdAt: Date
44
44
  }
45
45
 
46
- export interface SessionTurnResult<TOutput> {
47
- sessionId: string
48
- executionId: string
49
- turnNumber: number
50
- output: TOutput | null // Null for side-effect agents with no output schema
51
- duration: number
52
- }
46
+ export interface SessionTurnResult<TOutput> {
47
+ sessionId: string
48
+ executionId: string
49
+ /** Authoritative turn number claimed from locked session state before execution starts. */
50
+ lockedTurnNumber?: number
51
+ turnNumber: number
52
+ output: TOutput | null // Null for side-effect agents with no output schema
53
+ duration: number
54
+ }
53
55
 
54
56
  export interface CreateSessionParams {
55
57
  resourceId: string
@@ -1,3 +1,3 @@
1
1
  export const VERSION = {
2
- CURRENT: '1.13.4'
2
+ CURRENT: '1.13.7'
3
3
  }
@@ -7,11 +7,6 @@ export type Json =
7
7
  | Json[]
8
8
 
9
9
  export type Database = {
10
- // Allows to automatically instantiate createClient with right options
11
- // instead of createClient<Database, { PostgrestVersion: 'XX' }>(URL, KEY)
12
- __InternalSupabase: {
13
- PostgrestVersion: "12.2.3 (519615d)"
14
- }
15
10
  public: {
16
11
  Tables: {
17
12
  acq_artifacts: {
@@ -1211,6 +1206,74 @@ export type Database = {
1211
1206
  },
1212
1207
  ]
1213
1208
  }
1209
+ agent_access_grants: {
1210
+ Row: {
1211
+ allowed_origins: string[]
1212
+ branding: Json
1213
+ capture_fields: Json
1214
+ code_hash: string | null
1215
+ code_salt: string | null
1216
+ created_at: string
1217
+ disabled_at: string | null
1218
+ expires_at: string | null
1219
+ id: string
1220
+ max_sessions_per_visitor: number
1221
+ max_turns_per_session: number
1222
+ mode: string
1223
+ organization_id: string
1224
+ resource_id: string
1225
+ slug: string
1226
+ tool_policy: Json
1227
+ updated_at: string
1228
+ }
1229
+ Insert: {
1230
+ allowed_origins?: string[]
1231
+ branding?: Json
1232
+ capture_fields?: Json
1233
+ code_hash?: string | null
1234
+ code_salt?: string | null
1235
+ created_at?: string
1236
+ disabled_at?: string | null
1237
+ expires_at?: string | null
1238
+ id?: string
1239
+ max_sessions_per_visitor?: number
1240
+ max_turns_per_session?: number
1241
+ mode?: string
1242
+ organization_id: string
1243
+ resource_id: string
1244
+ slug: string
1245
+ tool_policy?: Json
1246
+ updated_at?: string
1247
+ }
1248
+ Update: {
1249
+ allowed_origins?: string[]
1250
+ branding?: Json
1251
+ capture_fields?: Json
1252
+ code_hash?: string | null
1253
+ code_salt?: string | null
1254
+ created_at?: string
1255
+ disabled_at?: string | null
1256
+ expires_at?: string | null
1257
+ id?: string
1258
+ max_sessions_per_visitor?: number
1259
+ max_turns_per_session?: number
1260
+ mode?: string
1261
+ organization_id?: string
1262
+ resource_id?: string
1263
+ slug?: string
1264
+ tool_policy?: Json
1265
+ updated_at?: string
1266
+ }
1267
+ Relationships: [
1268
+ {
1269
+ foreignKeyName: "agent_access_grants_organization_id_fkey"
1270
+ columns: ["organization_id"]
1271
+ isOneToOne: false
1272
+ referencedRelation: "organizations"
1273
+ referencedColumns: ["id"]
1274
+ },
1275
+ ]
1276
+ }
1214
1277
  api_keys: {
1215
1278
  Row: {
1216
1279
  created_at: string | null
@@ -2118,138 +2181,6 @@ export type Database = {
2118
2181
  }
2119
2182
  Relationships: []
2120
2183
  }
2121
- agent_access_grants: {
2122
- Row: {
2123
- allowed_origins: string[]
2124
- branding: Json
2125
- capture_fields: Json
2126
- code_hash: string | null
2127
- code_salt: string | null
2128
- created_at: string
2129
- disabled_at: string | null
2130
- expires_at: string | null
2131
- id: string
2132
- max_sessions_per_visitor: number
2133
- max_turns_per_session: number
2134
- mode: string
2135
- organization_id: string
2136
- resource_id: string
2137
- slug: string
2138
- tool_policy: Json
2139
- updated_at: string
2140
- }
2141
- Insert: {
2142
- allowed_origins?: string[]
2143
- branding?: Json
2144
- capture_fields?: Json
2145
- code_hash?: string | null
2146
- code_salt?: string | null
2147
- created_at?: string
2148
- disabled_at?: string | null
2149
- expires_at?: string | null
2150
- id?: string
2151
- max_sessions_per_visitor?: number
2152
- max_turns_per_session?: number
2153
- mode?: string
2154
- organization_id: string
2155
- resource_id: string
2156
- slug: string
2157
- tool_policy?: Json
2158
- updated_at?: string
2159
- }
2160
- Update: {
2161
- allowed_origins?: string[]
2162
- branding?: Json
2163
- capture_fields?: Json
2164
- code_hash?: string | null
2165
- code_salt?: string | null
2166
- created_at?: string
2167
- disabled_at?: string | null
2168
- expires_at?: string | null
2169
- id?: string
2170
- max_sessions_per_visitor?: number
2171
- max_turns_per_session?: number
2172
- mode?: string
2173
- organization_id?: string
2174
- resource_id?: string
2175
- slug?: string
2176
- tool_policy?: Json
2177
- updated_at?: string
2178
- }
2179
- Relationships: [
2180
- {
2181
- foreignKeyName: "agent_access_grants_organization_id_fkey"
2182
- columns: ["organization_id"]
2183
- isOneToOne: false
2184
- referencedRelation: "organizations"
2185
- referencedColumns: ["id"]
2186
- },
2187
- ]
2188
- }
2189
- agent_chat_capabilities: {
2190
- Row: {
2191
- created_at: string
2192
- expires_at: string
2193
- grant_id: string
2194
- id: string
2195
- organization_id: string
2196
- origin: string | null
2197
- resource_id: string
2198
- revoked_at: string | null
2199
- session_id: string | null
2200
- token_hash: string
2201
- visitor_id: string | null
2202
- }
2203
- Insert: {
2204
- created_at?: string
2205
- expires_at: string
2206
- grant_id: string
2207
- id?: string
2208
- organization_id: string
2209
- origin?: string | null
2210
- resource_id: string
2211
- revoked_at?: string | null
2212
- session_id?: string | null
2213
- token_hash: string
2214
- visitor_id?: string | null
2215
- }
2216
- Update: {
2217
- created_at?: string
2218
- expires_at?: string
2219
- grant_id?: string
2220
- id?: string
2221
- organization_id?: string
2222
- origin?: string | null
2223
- resource_id?: string
2224
- revoked_at?: string | null
2225
- session_id?: string | null
2226
- token_hash?: string
2227
- visitor_id?: string | null
2228
- }
2229
- Relationships: [
2230
- {
2231
- foreignKeyName: "agent_chat_capabilities_grant_id_fkey"
2232
- columns: ["grant_id"]
2233
- isOneToOne: false
2234
- referencedRelation: "agent_access_grants"
2235
- referencedColumns: ["id"]
2236
- },
2237
- {
2238
- foreignKeyName: "agent_chat_capabilities_organization_id_fkey"
2239
- columns: ["organization_id"]
2240
- isOneToOne: false
2241
- referencedRelation: "organizations"
2242
- referencedColumns: ["id"]
2243
- },
2244
- {
2245
- foreignKeyName: "agent_chat_capabilities_session_id_fkey"
2246
- columns: ["session_id"]
2247
- isOneToOne: false
2248
- referencedRelation: "sessions"
2249
- referencedColumns: ["session_id"]
2250
- },
2251
- ]
2252
- }
2253
2184
  organizations: {
2254
2185
  Row: {
2255
2186
  config: Json
@@ -3133,24 +3064,42 @@ export type Database = {
3133
3064
  [_ in never]: never
3134
3065
  }
3135
3066
  Functions: {
3136
- acq_default_checklist: { Args: { p_platform: string }; Returns: Json }
3067
+ acq_default_checklist: {
3068
+ Args: { p_platform: string }
3069
+ Returns: Json
3070
+ }
3137
3071
  append_deal_activity: {
3138
3072
  Args: { p_activity: Json; p_deal_id: string; p_organization_id: string }
3139
3073
  Returns: undefined
3140
3074
  }
3141
- auth_jwt_claims: { Args: never; Returns: Json }
3142
- auth_uid_safe: { Args: never; Returns: string }
3075
+ auth_jwt_claims: {
3076
+ Args: Record<PropertyKey, never>
3077
+ Returns: Json
3078
+ }
3079
+ auth_uid_safe: {
3080
+ Args: Record<PropertyKey, never>
3081
+ Returns: string
3082
+ }
3143
3083
  can_assign_role_in_org: {
3144
3084
  Args: { p_role_id: string; p_target_membership_id: string }
3145
3085
  Returns: boolean
3146
3086
  }
3147
- current_user_is_platform_admin: { Args: never; Returns: boolean }
3087
+ current_user_is_platform_admin: {
3088
+ Args: Record<PropertyKey, never>
3089
+ Returns: boolean
3090
+ }
3148
3091
  current_user_shares_org_with: {
3149
3092
  Args: { other_user_id: string }
3150
3093
  Returns: boolean
3151
3094
  }
3152
- current_user_supabase_id: { Args: never; Returns: string }
3153
- detect_stalled_executions: { Args: never; Returns: undefined }
3095
+ current_user_supabase_id: {
3096
+ Args: Record<PropertyKey, never>
3097
+ Returns: string
3098
+ }
3099
+ detect_stalled_executions: {
3100
+ Args: Record<PropertyKey, never>
3101
+ Returns: undefined
3102
+ }
3154
3103
  execute_session_turn: {
3155
3104
  Args: { p_session_id: string }
3156
3105
  Returns: {
@@ -3166,20 +3115,32 @@ export type Database = {
3166
3115
  user_id: string
3167
3116
  }[]
3168
3117
  }
3169
- get_platform_credential_kek: { Args: never; Returns: string }
3170
- get_storage_org_id: { Args: { file_path: string }; Returns: string }
3171
- get_workos_user_id: { Args: never; Returns: string }
3172
- has_org_access:
3173
- | {
3174
- Args: { action?: string; org_id: string; system_path: string }
3175
- Returns: boolean
3176
- }
3177
- | { Args: { action?: string; system_path: string }; Returns: boolean }
3118
+ get_platform_credential_kek: {
3119
+ Args: Record<PropertyKey, never>
3120
+ Returns: string
3121
+ }
3122
+ get_storage_org_id: {
3123
+ Args: { file_path: string }
3124
+ Returns: string
3125
+ }
3126
+ get_workos_user_id: {
3127
+ Args: Record<PropertyKey, never>
3128
+ Returns: string
3129
+ }
3130
+ has_org_access: {
3131
+ Args:
3132
+ | { action?: string; org_id: string; system_path: string }
3133
+ | { action?: string; system_path: string }
3134
+ Returns: boolean
3135
+ }
3178
3136
  has_org_permission: {
3179
3137
  Args: { org_id: string; perm_key: string }
3180
3138
  Returns: boolean
3181
3139
  }
3182
- is_org_member: { Args: { org_id: string }; Returns: boolean }
3140
+ is_org_member: {
3141
+ Args: { org_id: string }
3142
+ Returns: boolean
3143
+ }
3183
3144
  link_workos_membership_on_accept: {
3184
3145
  Args: {
3185
3146
  p_email: string
@@ -3196,10 +3157,16 @@ export type Database = {
3196
3157
  }
3197
3158
  Returns: Json
3198
3159
  }
3199
- process_due_schedules: { Args: never; Returns: Json }
3200
- recompute_all_memberships: { Args: never; Returns: undefined }
3160
+ process_due_schedules: {
3161
+ Args: Record<PropertyKey, never>
3162
+ Returns: Json
3163
+ }
3164
+ recompute_all_memberships: {
3165
+ Args: Record<PropertyKey, never>
3166
+ Returns: undefined
3167
+ }
3201
3168
  repair_membership_role_assignments: {
3202
- Args: never
3169
+ Args: Record<PropertyKey, never>
3203
3170
  Returns: {
3204
3171
  membership_id: string
3205
3172
  organization_id: string
@@ -3222,7 +3189,7 @@ export type Database = {
3222
3189
  Returns: string
3223
3190
  }
3224
3191
  upsert_user_profile: {
3225
- Args: never
3192
+ Args: Record<PropertyKey, never>
3226
3193
  Returns: {
3227
3194
  profile_display_name: string
3228
3195
  profile_email: string
@@ -3362,3 +3329,4 @@ export const Constants = {
3362
3329
  Enums: {},
3363
3330
  },
3364
3331
  } as const
3332
+