@gram-ai/elements 1.27.0 → 1.27.2

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.
Files changed (57) hide show
  1. package/dist/elements.cjs +1 -1
  2. package/dist/elements.js +1 -1
  3. package/dist/hooks/useAuth.d.ts +3 -1
  4. package/dist/hooks/useSession.d.ts +1 -0
  5. package/dist/{index-CP-wWZCV.cjs → index-CZ6AZT6Z.cjs} +49 -49
  6. package/dist/index-CZ6AZT6Z.cjs.map +1 -0
  7. package/dist/{index-oO5BAmPI.js → index-dPbw_95D.js} +6047 -5995
  8. package/dist/index-dPbw_95D.js.map +1 -0
  9. package/dist/lib/token.d.ts +12 -0
  10. package/dist/lib/token.test.d.ts +1 -0
  11. package/dist/{profiler-ECh1zoXF.js → profiler-D1ZeY9EE.js} +2 -2
  12. package/dist/{profiler-ECh1zoXF.js.map → profiler-D1ZeY9EE.js.map} +1 -1
  13. package/dist/{profiler-CEpc7O5Q.cjs → profiler-iUZI0bb_.cjs} +2 -2
  14. package/dist/{profiler-CEpc7O5Q.cjs.map → profiler-iUZI0bb_.cjs.map} +1 -1
  15. package/dist/server/bun.cjs +1 -1
  16. package/dist/server/bun.cjs.map +1 -1
  17. package/dist/server/bun.js +1 -1
  18. package/dist/server/core.cjs +2 -0
  19. package/dist/server/core.cjs.map +1 -0
  20. package/dist/{core-Cqad6-xW.js → server/core.js} +5 -5
  21. package/dist/server/core.js.map +1 -0
  22. package/dist/server/express.cjs +1 -1
  23. package/dist/server/express.cjs.map +1 -1
  24. package/dist/server/express.js +1 -1
  25. package/dist/server/fastify.cjs +1 -1
  26. package/dist/server/fastify.cjs.map +1 -1
  27. package/dist/server/fastify.js +6 -6
  28. package/dist/server/hono.cjs +1 -1
  29. package/dist/server/hono.cjs.map +1 -1
  30. package/dist/server/hono.js +3 -3
  31. package/dist/server/nextjs.cjs +1 -1
  32. package/dist/server/nextjs.cjs.map +1 -1
  33. package/dist/server/nextjs.js +1 -1
  34. package/dist/server/tanstack-start.cjs +1 -1
  35. package/dist/server/tanstack-start.cjs.map +1 -1
  36. package/dist/server/tanstack-start.d.ts +0 -14
  37. package/dist/server/tanstack-start.js +11 -24
  38. package/dist/server/tanstack-start.js.map +1 -1
  39. package/dist/server.cjs +1 -1
  40. package/dist/server.cjs.map +1 -1
  41. package/dist/server.js +1 -1
  42. package/dist/{startRecording-qDCAu4Q0.cjs → startRecording-BssI1M_6.cjs} +2 -2
  43. package/dist/{startRecording-qDCAu4Q0.cjs.map → startRecording-BssI1M_6.cjs.map} +1 -1
  44. package/dist/{startRecording-CmZjjJoz.js → startRecording-RyH9ZWER.js} +2 -2
  45. package/dist/{startRecording-CmZjjJoz.js.map → startRecording-RyH9ZWER.js.map} +1 -1
  46. package/package.json +6 -1
  47. package/src/contexts/ElementsProvider.tsx +26 -7
  48. package/src/hooks/useAuth.ts +51 -3
  49. package/src/hooks/useSession.ts +7 -10
  50. package/src/lib/token.test.ts +79 -0
  51. package/src/lib/token.ts +39 -0
  52. package/src/server/tanstack-start.ts +14 -47
  53. package/dist/core-Cqad6-xW.js.map +0 -1
  54. package/dist/core-DBxmxwCi.cjs +0 -2
  55. package/dist/core-DBxmxwCi.cjs.map +0 -1
  56. package/dist/index-CP-wWZCV.cjs.map +0 -1
  57. package/dist/index-oO5BAmPI.js.map +0 -1
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@gram-ai/elements",
3
3
  "description": "Gram Elements is a library of UI primitives for building chat-like experiences for MCP Servers.",
4
4
  "type": "module",
5
- "version": "1.27.0",
5
+ "version": "1.27.2",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
8
8
  ".": {
@@ -15,6 +15,11 @@
15
15
  "import": "./dist/server.js",
16
16
  "require": "./dist/server.cjs"
17
17
  },
18
+ "./server/core": {
19
+ "types": "./dist/server/core.d.ts",
20
+ "import": "./dist/server/core.js",
21
+ "require": "./dist/server/core.cjs"
22
+ },
18
23
  "./server/express": {
19
24
  "types": "./dist/server/express.d.ts",
20
25
  "import": "./dist/server/express.js",
@@ -25,8 +25,8 @@ import { Plugin } from '@/types/plugins'
25
25
  import {
26
26
  AssistantRuntimeProvider,
27
27
  AssistantTool,
28
- unstable_useRemoteThreadListRuntime as useRemoteThreadListRuntime,
29
28
  useAssistantState,
29
+ unstable_useRemoteThreadListRuntime as useRemoteThreadListRuntime,
30
30
  } from '@assistant-ui/react'
31
31
  import {
32
32
  frontendTools as convertFrontendToolsToAISDKTools,
@@ -36,6 +36,7 @@ import { createOpenRouter } from '@openrouter/ai-sdk-provider'
36
36
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
37
37
  import {
38
38
  convertToModelMessages,
39
+ createUIMessageStream,
39
40
  smoothStream,
40
41
  stepCountIs,
41
42
  streamText,
@@ -52,14 +53,14 @@ import {
52
53
  useState,
53
54
  } from 'react'
54
55
  import { useAuth } from '../hooks/useAuth'
55
- import { ElementsContext } from './contexts'
56
- import { ToolApprovalProvider } from './ToolApprovalContext'
56
+ import { ChatIdContext } from './ChatIdContext'
57
57
  import {
58
58
  ConnectionStatusProvider,
59
59
  useConnectionStatusOptional,
60
60
  } from './ConnectionStatusContext'
61
+ import { ElementsContext } from './contexts'
62
+ import { ToolApprovalProvider } from './ToolApprovalContext'
61
63
  import { ToolExecutionProvider } from './ToolExecutionContext'
62
- import { ChatIdContext } from './ChatIdContext'
63
64
 
64
65
  /**
65
66
  * Extracts executable tools from frontend tool definitions.
@@ -158,6 +159,10 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
158
159
  auth: config.api,
159
160
  projectSlug: config.projectSlug,
160
161
  })
162
+
163
+ // Ref to access ensureValidHeaders in async transport without stale closures
164
+ const ensureValidHeadersRef = useRef(auth.ensureValidHeaders)
165
+ ensureValidHeadersRef.current = auth.ensureValidHeaders
161
166
  const toolApproval = useToolApproval()
162
167
 
163
168
  const [model, setModel] = useState<Model>(
@@ -266,6 +271,9 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
266
271
  throw new Error('Session is loading')
267
272
  }
268
273
 
274
+ // Ensure the session token is still valid; refresh if expired
275
+ const validHeaders = await ensureValidHeadersRef.current()
276
+
269
277
  // Get chat ID - use the synced remoteId ref first (history mode),
270
278
  // fall back to generated ID (non-history mode)
271
279
  let chatId = currentRemoteIdRef.current
@@ -318,7 +326,7 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
318
326
 
319
327
  // Include Gram-Chat-ID header for chat persistence and Gram-Environment for environment selection
320
328
  const headersWithChatId = {
321
- ...auth.headers,
329
+ ...validHeaders,
322
330
  'Gram-Chat-ID': chatId,
323
331
  'X-Gram-Source': 'elements',
324
332
  ...config.api?.headers, // We do this after X-Gram-Source so the playground can override it
@@ -327,6 +335,13 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
327
335
  }),
328
336
  }
329
337
 
338
+ // Update MCP headers with the (possibly refreshed) session token
339
+ // so mid-stream MCP tool calls use the fresh token
340
+ const freshSession = validHeaders['Gram-Chat-Session']
341
+ if (freshSession) {
342
+ mcpHeaders['Gram-Chat-Session'] = freshSession
343
+ }
344
+
330
345
  // Create OpenRouter model (only needed when not using custom model)
331
346
  const openRouterModel = usingCustomModel
332
347
  ? null
@@ -395,7 +410,12 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
395
410
  // Mark as connected when stream starts successfully
396
411
  connectionStatus?.markConnected()
397
412
 
398
- return result.toUIMessageStream()
413
+ // This weird construction is necessary to get errors to propagate properly to assistant-ui
414
+ return createUIMessageStream({
415
+ execute: ({ writer }) => {
416
+ writer.merge(result.toUIMessageStream())
417
+ },
418
+ })
399
419
  } catch (error) {
400
420
  console.error('Error creating stream:', error)
401
421
  trackError(error, { source: 'stream-creation' })
@@ -430,7 +450,6 @@ const ElementsProviderInner = ({ children, config }: ElementsProviderProps) => {
430
450
  mcpTools,
431
451
  getApprovalHelpers,
432
452
  apiUrl,
433
- auth.headers,
434
453
  auth.isLoading,
435
454
  connectionStatus,
436
455
  ]
@@ -1,14 +1,17 @@
1
1
  import { useReplayContext } from '@/contexts/ReplayContext'
2
2
  import {
3
3
  hasExplicitSessionAuth,
4
+ isAnyStaticSession,
4
5
  isDangerousApiKeyAuth,
5
6
  isStaticSessionAuth,
6
7
  isUnifiedFunctionSession,
7
8
  isUnifiedStaticSession,
8
9
  } from '@/lib/auth'
9
- import { useMemo } from 'react'
10
+ import { getTokenExpiry } from '@/lib/token'
11
+ import { useCallback, useMemo } from 'react'
10
12
  import { ApiConfig, GetSessionFn } from '../types'
11
- import { useSession } from './useSession'
13
+ import { getChatSessionQueryKey, useSession } from './useSession'
14
+ import { useQueryClient } from '@tanstack/react-query'
12
15
 
13
16
  declare const __GRAM_API_URL__: string | undefined
14
17
 
@@ -16,10 +19,12 @@ export type Auth =
16
19
  | {
17
20
  headers: Record<string, string>
18
21
  isLoading: false
22
+ ensureValidHeaders: () => Promise<Record<string, string>>
19
23
  }
20
24
  | {
21
25
  headers?: Record<string, string>
22
26
  isLoading: true
27
+ ensureValidHeaders: () => Promise<Record<string, string>>
23
28
  }
24
29
 
25
30
  async function defaultGetSession(init: {
@@ -62,7 +67,7 @@ function createDangerousApiKeySessionFn(
62
67
 
63
68
  /**
64
69
  * Hook to fetch or retrieve the session token for the chat.
65
- * @returns The session token string or null
70
+ * @returns Auth object with headers and ensureValidHeaders for pre-request token refresh
66
71
  */
67
72
  export const useAuth = ({
68
73
  projectSlug,
@@ -73,6 +78,7 @@ export const useAuth = ({
73
78
  }): Auth => {
74
79
  const replayCtx = useReplayContext()
75
80
  const isReplay = replayCtx?.isReplay ?? false
81
+ const queryClient = useQueryClient()
76
82
 
77
83
  const apiUrl = useMemo(() => {
78
84
  const envUrl =
@@ -117,17 +123,58 @@ export const useAuth = ({
117
123
  projectSlug,
118
124
  })
119
125
 
126
+ const shouldRefresh = !isAnyStaticSession(auth) && !isReplay
127
+
128
+ const ensureValidHeaders = useCallback(async (): Promise<
129
+ Record<string, string>
130
+ > => {
131
+ const queryKey = getChatSessionQueryKey(projectSlug)
132
+ const cachedToken = queryClient.getQueryData<string>(queryKey)
133
+
134
+ if (!shouldRefresh || !getSession) {
135
+ return {
136
+ 'Gram-Project': projectSlug,
137
+ ...(cachedToken && { 'Gram-Chat-Session': cachedToken }),
138
+ }
139
+ }
140
+
141
+ // Check if the cached token is expired (or within 30s of expiry).
142
+ // staleTime=0 forces a refetch; Infinity keeps the cached value.
143
+ const exp = cachedToken ? getTokenExpiry(cachedToken) : null
144
+ const isExpired = exp !== null && Date.now() >= exp * 1000 - 30_000
145
+ const staleTime = isExpired ? 0 : Infinity
146
+
147
+ try {
148
+ const token = await queryClient.fetchQuery({
149
+ queryKey,
150
+ queryFn: () => getSession({ projectSlug }),
151
+ staleTime,
152
+ })
153
+ return {
154
+ 'Gram-Project': projectSlug,
155
+ ...(token && { 'Gram-Chat-Session': token }),
156
+ }
157
+ } catch {
158
+ return {
159
+ 'Gram-Project': projectSlug,
160
+ ...(cachedToken && { 'Gram-Chat-Session': cachedToken }),
161
+ }
162
+ }
163
+ }, [shouldRefresh, getSession, projectSlug, queryClient])
164
+
120
165
  // In replay mode, return immediately without waiting for session
121
166
  if (isReplay) {
122
167
  return {
123
168
  headers: {},
124
169
  isLoading: false,
170
+ ensureValidHeaders: async () => ({}),
125
171
  }
126
172
  }
127
173
 
128
174
  return !session
129
175
  ? {
130
176
  isLoading: true,
177
+ ensureValidHeaders,
131
178
  }
132
179
  : {
133
180
  headers: {
@@ -135,5 +182,6 @@ export const useAuth = ({
135
182
  'Gram-Chat-Session': session,
136
183
  },
137
184
  isLoading: false,
185
+ ensureValidHeaders,
138
186
  }
139
187
  }
@@ -1,6 +1,10 @@
1
1
  import { GetSessionFn } from '@/types'
2
2
  import { useQuery, useQueryClient } from '@tanstack/react-query'
3
3
 
4
+ export function getChatSessionQueryKey(projectSlug: string) {
5
+ return ['chatSession', projectSlug] as const
6
+ }
7
+
4
8
  /**
5
9
  * Hook to fetch or retrieve the session token for the chat.
6
10
  * @returns The session token string or null
@@ -13,21 +17,14 @@ export const useSession = ({
13
17
  projectSlug: string
14
18
  }): string | null => {
15
19
  const queryClient = useQueryClient()
16
- const queryKey = ['chatSession', projectSlug]
20
+ const queryKey = getChatSessionQueryKey(projectSlug)
17
21
 
18
- const queryState = queryClient.getQueryState(queryKey)
19
- const hasData = queryState?.data !== undefined
20
- // Check if data is stale - with staleTime: Infinity, data never becomes stale
21
- // but we check dataUpdatedAt to determine if we should refetch
22
- const dataUpdatedAt = queryState?.dataUpdatedAt ?? 0
23
- const staleTime = Infinity // Matches the staleTime in useQuery options
24
- const isStale = hasData && Date.now() - dataUpdatedAt > staleTime
25
- const shouldFetch = !hasData || isStale
22
+ const hasData = queryClient.getQueryState(queryKey)?.data !== undefined
26
23
 
27
24
  const { data: fetchedSessionToken } = useQuery({
28
25
  queryKey,
29
26
  queryFn: () => getSession!({ projectSlug }),
30
- enabled: shouldFetch && getSession !== null,
27
+ enabled: !hasData && getSession !== null,
31
28
  staleTime: Infinity, // Session tokens don't need to be refetched
32
29
  gcTime: Infinity, // Keep in cache indefinitely
33
30
  })
@@ -0,0 +1,79 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { getTokenExpiry, isTokenExpired } from './token'
3
+
4
+ /** Helper: build a JWT with a given payload (no signature verification needed). */
5
+ function makeJwt(payload: Record<string, unknown>): string {
6
+ const header = btoa(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))
7
+ const body = btoa(JSON.stringify(payload))
8
+ return `${header}.${body}.fake-signature`
9
+ }
10
+
11
+ describe('getTokenExpiry', () => {
12
+ it('returns exp for a valid JWT', () => {
13
+ const exp = 1700000000
14
+ expect(getTokenExpiry(makeJwt({ exp }))).toBe(exp)
15
+ })
16
+
17
+ it('returns null when exp is missing', () => {
18
+ expect(getTokenExpiry(makeJwt({ sub: 'user' }))).toBeNull()
19
+ })
20
+
21
+ it('returns null for a non-JWT string', () => {
22
+ expect(getTokenExpiry('not-a-jwt')).toBeNull()
23
+ })
24
+
25
+ it('returns null for an empty string', () => {
26
+ expect(getTokenExpiry('')).toBeNull()
27
+ })
28
+
29
+ it('returns null when payload is not valid JSON', () => {
30
+ // Two dots but the middle segment is not valid base64 JSON
31
+ expect(getTokenExpiry('a.!!!.b')).toBeNull()
32
+ })
33
+
34
+ it('handles base64url characters (- and _)', () => {
35
+ // Manually craft a payload with base64url-specific chars
36
+ const payload = { exp: 1700000000 }
37
+ const json = JSON.stringify(payload)
38
+ const b64 = btoa(json)
39
+ .replace(/\+/g, '-')
40
+ .replace(/\//g, '_')
41
+ .replace(/=+$/, '')
42
+ const token = `header.${b64}.sig`
43
+ expect(getTokenExpiry(token)).toBe(1700000000)
44
+ })
45
+ })
46
+
47
+ describe('isTokenExpired', () => {
48
+ it('returns true for an expired token', () => {
49
+ // exp = 1 second ago
50
+ const exp = Math.floor(Date.now() / 1000) - 1
51
+ expect(isTokenExpired(makeJwt({ exp }))).toBe(true)
52
+ })
53
+
54
+ it('returns true when token is within the buffer window', () => {
55
+ // exp = 20 seconds from now (within 30s default buffer)
56
+ const exp = Math.floor(Date.now() / 1000) + 20
57
+ expect(isTokenExpired(makeJwt({ exp }))).toBe(true)
58
+ })
59
+
60
+ it('returns false when token is well outside the buffer', () => {
61
+ // exp = 5 minutes from now
62
+ const exp = Math.floor(Date.now() / 1000) + 300
63
+ expect(isTokenExpired(makeJwt({ exp }))).toBe(false)
64
+ })
65
+
66
+ it('respects a custom buffer', () => {
67
+ // exp = 20 seconds from now, buffer = 10s → should NOT be expired
68
+ const exp = Math.floor(Date.now() / 1000) + 20
69
+ expect(isTokenExpired(makeJwt({ exp }), 10_000)).toBe(false)
70
+ })
71
+
72
+ it('returns false (fail-open) for a non-JWT string', () => {
73
+ expect(isTokenExpired('opaque-session-token')).toBe(false)
74
+ })
75
+
76
+ it('returns false (fail-open) for an empty string', () => {
77
+ expect(isTokenExpired('')).toBe(false)
78
+ })
79
+ })
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Extracts the `exp` claim from a JWT token without verifying the signature.
3
+ * Returns the expiry as a Unix timestamp (seconds), or null if the token
4
+ * is not a valid JWT or has no `exp` claim.
5
+ */
6
+ export function getTokenExpiry(token: string): number | null {
7
+ try {
8
+ const parts = token.split('.')
9
+ if (parts.length !== 3) return null
10
+
11
+ // base64url → base64 → decode
12
+ let payload = parts[1].replace(/-/g, '+').replace(/_/g, '/')
13
+ while (payload.length % 4) payload += '='
14
+
15
+ const json = atob(payload)
16
+ const parsed = JSON.parse(json)
17
+
18
+ if (typeof parsed.exp === 'number') {
19
+ return parsed.exp
20
+ }
21
+ return null
22
+ } catch {
23
+ return null
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Returns true when the token is expired or within `bufferMs` milliseconds
29
+ * of expiry. Fails open (returns false) for non-JWT tokens or tokens
30
+ * without an `exp` claim so they pass through unchanged.
31
+ */
32
+ export function isTokenExpired(
33
+ token: string,
34
+ bufferMs: number = 30_000
35
+ ): boolean {
36
+ const exp = getTokenExpiry(token)
37
+ if (exp === null) return false // fail-open for non-JWT tokens
38
+ return Date.now() >= exp * 1000 - bufferMs
39
+ }
@@ -1,70 +1,37 @@
1
1
  /**
2
2
  * TanStack Start adapter for Gram Elements server handlers.
3
3
  *
4
- * Provides two approaches for session creation:
4
+ * Use `createTanStackStartHandler` to create a handler for TanStack Start
5
+ * server routes that manages chat session creation.
5
6
  *
6
- * 1. **Server Function (RPC)** — use `createTanStackStartSessionFn` to create
7
- * a `createServerFn` that can be called directly from client code and passed
8
- * to `session` in the Elements config.
9
- *
10
- * 2. **API Route** — use `createTanStackStartHandler` to create a handler for
11
- * TanStack Start server routes (similar to the Next.js adapter).
12
- *
13
- * @example Server Function approach
7
+ * @example
14
8
  * ```typescript
15
- * // session.functions.ts
16
- * import { createTanStackStartSessionFn } from '@gram-ai/elements/server/tanstack-start'
9
+ * // routes/api/chat.session.ts
10
+ * import { createTanStackStartHandler } from '@gram-ai/elements/server/tanstack-start'
17
11
  *
18
- * export const getSession = createTanStackStartSessionFn({
12
+ * export const POST = createTanStackStartHandler({
19
13
  * embedOrigin: 'http://localhost:3000',
20
14
  * userIdentifier: 'user-123',
21
15
  * expiresAfter: 3600,
22
16
  * })
23
17
  * ```
24
18
  *
25
- * @example API Route approach
19
+ * @example Dynamic configuration
26
20
  * ```typescript
27
21
  * // routes/api/chat.session.ts
28
- * import { createTanStackStartHandler } from '@gram-ai/elements/server/tanstack-start'
29
- *
30
- * const handler = createTanStackStartHandler({
31
- * embedOrigin: 'http://localhost:3000',
32
- * userIdentifier: 'user-123',
33
- * expiresAfter: 3600,
22
+ * export const POST = createTanStackStartHandler(async (request) => {
23
+ * const user = await getUserFromRequest(request)
24
+ * return {
25
+ * embedOrigin: 'http://localhost:3000',
26
+ * userIdentifier: user.id,
27
+ * expiresAfter: 3600,
28
+ * }
34
29
  * })
35
30
  * ```
36
31
  */
37
32
 
38
- import { createServerFn } from '@tanstack/react-start'
39
33
  import { createChatSession, type SessionHandlerOptions } from './core'
40
34
 
41
- /**
42
- * Create a TanStack Start server function for session creation.
43
- *
44
- * The returned function can be called from client code (RPC-style) and passed
45
- * to `session` in the Gram Elements config.
46
- *
47
- * @param options - Session configuration options
48
- * @returns A `createServerFn` instance callable from the client
49
- */
50
- export function createTanStackStartSessionFn(options: SessionHandlerOptions) {
51
- return createServerFn({ method: 'POST' })
52
- .inputValidator((data: { projectSlug: string }) => data)
53
- .handler(async ({ data }) => {
54
- const result = await createChatSession({
55
- projectSlug: data.projectSlug,
56
- options,
57
- })
58
-
59
- if (result.status !== 200) {
60
- throw new Error(`Failed to create chat session: ${result.body}`)
61
- }
62
-
63
- const parsed = JSON.parse(result.body) as { client_token: string }
64
- return parsed.client_token
65
- })
66
- }
67
-
68
35
  /**
69
36
  * Create a TanStack Start server route handler for the chat session endpoint.
70
37
  *
@@ -1 +0,0 @@
1
- {"version":3,"file":"core-Cqad6-xW.js","sources":["../src/server/core.ts"],"sourcesContent":null,"names":["createChatSession","request","base","response","body","error","errorMessage"],"mappings":"AA2CA,eAAsBA,EACpBC,GACgC;AAChC,QAAMC,IAAO,QAAQ,IAAI,gBAAgB;AAEzC,MAAI;AACF,UAAMC,IAAW,MAAM,MAAMD,IAAO,4BAA4B;AAAA,MAC9D,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB,cAAcD,EAAQ,QAAQ;AAAA,QAC9B,iBAAiBA,EAAQ,QAAQ;AAAA,QACjC,eAAeA,EAAQ,QAAQ;AAAA,MAAA,CAChC;AAAA,MACD,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,gBAAgBA,EAAQ;AAAA,QACxB,YAAYA,EAAQ,QAAQ,UAAU,QAAQ,IAAI,gBAAgB;AAAA,MAAA;AAAA,IACpE,CACD,GAEKG,IAAO,MAAMD,EAAS,KAAA;AAE5B,WAAO;AAAA,MACL,QAAQA,EAAS;AAAA,MACjB,MAAAC;AAAA,MACA,SAAS,EAAE,gBAAgB,mBAAA;AAAA,IAAmB;AAAA,EAElD,SAASC,GAAO;AACd,UAAMC,IACJD,aAAiB,QAAQA,EAAM,UAAU;AAC3C,mBAAQ,MAAM,kCAAkCA,CAAK,GAE9C;AAAA,MACL,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB,OAAO,oCAAoCC;AAAA,MAAA,CAC5C;AAAA,MACD,SAAS,EAAE,gBAAgB,mBAAA;AAAA,IAAmB;AAAA,EAElD;AACF;"}
@@ -1,2 +0,0 @@
1
- "use strict";async function r(t){const o=process.env.GRAM_API_URL??"https://app.getgram.ai";try{const e=await fetch(o+"/rpc/chatSessions.create",{method:"POST",body:JSON.stringify({embed_origin:t.options.embedOrigin,user_identifier:t.options.userIdentifier,expires_after:t.options.expiresAfter}),headers:{"Content-Type":"application/json","Gram-Project":t.projectSlug,"Gram-Key":t.options.apiKey??process.env.GRAM_API_KEY??""}}),s=await e.text();return{status:e.status,body:s,headers:{"Content-Type":"application/json"}}}catch(e){const s=e instanceof Error?e.message:"Unknown error";return console.error("Failed to create chat session:",e),{status:500,body:JSON.stringify({error:"Failed to create chat session: "+s}),headers:{"Content-Type":"application/json"}}}}exports.createChatSession=r;
2
- //# sourceMappingURL=core-DBxmxwCi.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"core-DBxmxwCi.cjs","sources":["../src/server/core.ts"],"sourcesContent":null,"names":["createChatSession","request","base","response","body","error","errorMessage"],"mappings":"aA2CA,eAAsBA,EACpBC,EACgC,CAChC,MAAMC,EAAO,QAAQ,IAAI,cAAgB,yBAEzC,GAAI,CACF,MAAMC,EAAW,MAAM,MAAMD,EAAO,2BAA4B,CAC9D,OAAQ,OACR,KAAM,KAAK,UAAU,CACnB,aAAcD,EAAQ,QAAQ,YAC9B,gBAAiBA,EAAQ,QAAQ,eACjC,cAAeA,EAAQ,QAAQ,YAAA,CAChC,EACD,QAAS,CACP,eAAgB,mBAChB,eAAgBA,EAAQ,YACxB,WAAYA,EAAQ,QAAQ,QAAU,QAAQ,IAAI,cAAgB,EAAA,CACpE,CACD,EAEKG,EAAO,MAAMD,EAAS,KAAA,EAE5B,MAAO,CACL,OAAQA,EAAS,OACjB,KAAAC,EACA,QAAS,CAAE,eAAgB,kBAAA,CAAmB,CAElD,OAASC,EAAO,CACd,MAAMC,EACJD,aAAiB,MAAQA,EAAM,QAAU,gBAC3C,eAAQ,MAAM,iCAAkCA,CAAK,EAE9C,CACL,OAAQ,IACR,KAAM,KAAK,UAAU,CACnB,MAAO,kCAAoCC,CAAA,CAC5C,EACD,QAAS,CAAE,eAAgB,kBAAA,CAAmB,CAElD,CACF"}