@tangle-network/agent-app 0.47.15 → 0.47.16
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/README.md +8 -0
- package/dist/DesignCanvas-UPRRA4YG.js +11 -0
- package/dist/DesignCanvasEditor-GVJO5SMH.js +14 -0
- package/dist/app-auth/index.js +3 -2
- package/dist/app-auth/index.js.map +1 -1
- package/dist/assistant/index.js +7 -6
- package/dist/assistant/index.js.map +1 -1
- package/dist/chat-react/index.js +4 -3
- package/dist/chat-routes/index.js +12 -6
- package/dist/chat-routes/index.js.map +1 -1
- package/dist/chat-routes/wire.d.ts +3 -3
- package/dist/chat-store/index.js +3 -2
- package/dist/chat-store/index.js.map +1 -1
- package/dist/{chunk-LYAYNWDS.js → chunk-3GVFJYLO.js} +4 -4
- package/dist/{chunk-F7VH4G5C.js → chunk-3YUI7WNW.js} +1 -1
- package/dist/{chunk-F7VH4G5C.js.map → chunk-3YUI7WNW.js.map} +1 -1
- package/dist/{chunk-IRYULX3R.js → chunk-4PZE7XAM.js} +2 -2
- package/dist/{chunk-7LJYCHXK.js → chunk-54KJ54SY.js} +3 -3
- package/dist/{chunk-DRB77FYL.js → chunk-A2XMTCER.js} +2 -2
- package/dist/{chunk-UB4LENR5.js → chunk-AXJV66PC.js} +2 -2
- package/dist/{chunk-HZVVO6VR.js → chunk-FQYAJYPW.js} +11 -4
- package/dist/chunk-FQYAJYPW.js.map +1 -0
- package/dist/{chunk-X5DQ5QOP.js → chunk-G4CPEJNN.js} +2 -2
- package/dist/{chunk-TTYJIMTR.js → chunk-H6R3VYAZ.js} +334 -164
- package/dist/chunk-H6R3VYAZ.js.map +1 -0
- package/dist/{chunk-33BN7P57.js → chunk-HUYTN7RI.js} +5 -5
- package/dist/{chunk-SUO2R2ET.js → chunk-NU7QSZBR.js} +2 -2
- package/dist/{chunk-OYTMILRK.js → chunk-QEPLXYOE.js} +2 -2
- package/dist/{chunk-FMEL7VJR.js → chunk-TNWQA5XJ.js} +2 -2
- package/dist/chunk-TXD5HXLE.js +14 -0
- package/dist/chunk-TXD5HXLE.js.map +1 -0
- package/dist/{chunk-UMV45ZDF.js → chunk-WOZSOPUZ.js} +3 -3
- package/dist/{chunk-DXHUQ5NO.js → chunk-X47R2IVO.js} +8 -1
- package/dist/chunk-X47R2IVO.js.map +1 -0
- package/dist/design-canvas/index.js +3 -2
- package/dist/design-canvas/index.js.map +1 -1
- package/dist/design-canvas-react/engine.js +5 -4
- package/dist/design-canvas-react/index.js +8 -7
- package/dist/design-canvas-react/index.js.map +1 -1
- package/dist/design-canvas-react/lazy.js +1 -1
- package/dist/platform/api-key-auth.d.ts +27 -0
- package/dist/platform/index.d.ts +1 -0
- package/dist/platform/index.js +47 -2
- package/dist/platform/index.js.map +1 -1
- package/dist/public-consultation/index.d.ts +1 -1
- package/dist/public-consultation/index.js +5 -4
- package/dist/public-consultation/index.js.map +1 -1
- package/dist/sequences/index.js +2 -1
- package/dist/sequences/index.js.map +1 -1
- package/dist/web/file-export.d.ts +6 -0
- package/dist/web/index.d.ts +1 -0
- package/dist/web/index.js +5 -1
- package/dist/web-react/api-access-panel.d.ts +33 -0
- package/dist/web-react/index.d.ts +1 -0
- package/dist/web-react/index.js +9 -6
- package/package.json +1 -1
- package/dist/DesignCanvas-JRBCAWHW.js +0 -10
- package/dist/DesignCanvasEditor-J2OLS22G.js +0 -13
- package/dist/chunk-DXHUQ5NO.js.map +0 -1
- package/dist/chunk-HZVVO6VR.js.map +0 -1
- package/dist/chunk-TTYJIMTR.js.map +0 -1
- /package/dist/{DesignCanvas-JRBCAWHW.js.map → DesignCanvas-UPRRA4YG.js.map} +0 -0
- /package/dist/{DesignCanvasEditor-J2OLS22G.js.map → DesignCanvasEditor-GVJO5SMH.js.map} +0 -0
- /package/dist/{chunk-LYAYNWDS.js.map → chunk-3GVFJYLO.js.map} +0 -0
- /package/dist/{chunk-IRYULX3R.js.map → chunk-4PZE7XAM.js.map} +0 -0
- /package/dist/{chunk-7LJYCHXK.js.map → chunk-54KJ54SY.js.map} +0 -0
- /package/dist/{chunk-DRB77FYL.js.map → chunk-A2XMTCER.js.map} +0 -0
- /package/dist/{chunk-UB4LENR5.js.map → chunk-AXJV66PC.js.map} +0 -0
- /package/dist/{chunk-X5DQ5QOP.js.map → chunk-G4CPEJNN.js.map} +0 -0
- /package/dist/{chunk-33BN7P57.js.map → chunk-HUYTN7RI.js.map} +0 -0
- /package/dist/{chunk-SUO2R2ET.js.map → chunk-NU7QSZBR.js.map} +0 -0
- /package/dist/{chunk-OYTMILRK.js.map → chunk-QEPLXYOE.js.map} +0 -0
- /package/dist/{chunk-FMEL7VJR.js.map → chunk-TNWQA5XJ.js.map} +0 -0
- /package/dist/{chunk-UMV45ZDF.js.map → chunk-WOZSOPUZ.js.map} +0 -0
package/README.md
CHANGED
|
@@ -166,6 +166,14 @@ The **complete, always-current reference** — every published subpath, its expo
|
|
|
166
166
|
|
|
167
167
|
See **[`docs/CODEMAP.md`](./docs/CODEMAP.md)** for the rest — `/billing`, `/tangle`, `/object-store`, `/trace`, `/theme`, `/eval`, `/app-auth`, `/platform`, and more.
|
|
168
168
|
|
|
169
|
+
`createApiKeyRequestAuth` from `/platform` lets private product routes accept existing scoped Bearer keys.
|
|
170
|
+
`ApiAccessPanel` from `/web-react` provides reusable owner key creation, one-time copying, and revocation.
|
|
171
|
+
See [private API adoption](examples/private-api-access.md) for server and owner-page integration.
|
|
172
|
+
Provide the maintained key verifier, an exact route-to-scope policy, owner lookup, and an atomic request-quota claim.
|
|
173
|
+
The adapter requires finite expiry and explicit scope, and never falls back to cookies when a supplied credential fails.
|
|
174
|
+
Keep key issuance cookie-only and retain workspace authorization in each product route.
|
|
175
|
+
Execution still requires the product's billing checks; capped keys require a reservation and settlement path that enforces their cap.
|
|
176
|
+
|
|
169
177
|
### Missions: id shape and product columns
|
|
170
178
|
|
|
171
179
|
Two `createMissionService` seams adopters hit on day one:
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DesignCanvas
|
|
3
|
+
} from "./chunk-54KJ54SY.js";
|
|
4
|
+
import "./chunk-G4CPEJNN.js";
|
|
5
|
+
import "./chunk-A2XMTCER.js";
|
|
6
|
+
import "./chunk-3YUI7WNW.js";
|
|
7
|
+
import "./chunk-TXD5HXLE.js";
|
|
8
|
+
export {
|
|
9
|
+
DesignCanvas
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=DesignCanvas-UPRRA4YG.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DesignCanvasEditor
|
|
3
|
+
} from "./chunk-HUYTN7RI.js";
|
|
4
|
+
import "./chunk-54KJ54SY.js";
|
|
5
|
+
import "./chunk-Q2QKEV6J.js";
|
|
6
|
+
import "./chunk-QEPLXYOE.js";
|
|
7
|
+
import "./chunk-G4CPEJNN.js";
|
|
8
|
+
import "./chunk-A2XMTCER.js";
|
|
9
|
+
import "./chunk-3YUI7WNW.js";
|
|
10
|
+
import "./chunk-TXD5HXLE.js";
|
|
11
|
+
export {
|
|
12
|
+
DesignCanvasEditor
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=DesignCanvasEditor-GVJO5SMH.js.map
|
package/dist/app-auth/index.js
CHANGED
|
@@ -2,9 +2,10 @@ import {
|
|
|
2
2
|
createAuthGuard,
|
|
3
3
|
createBetterAuthSessionCookieMinter,
|
|
4
4
|
createTangleSsoHandlers
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-AXJV66PC.js";
|
|
6
6
|
import "../chunk-JML7WKWU.js";
|
|
7
|
-
import "../chunk-
|
|
7
|
+
import "../chunk-3YUI7WNW.js";
|
|
8
|
+
import "../chunk-TXD5HXLE.js";
|
|
8
9
|
|
|
9
10
|
// src/app-auth/index.ts
|
|
10
11
|
import { betterAuth } from "better-auth";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/app-auth/index.ts"],"sourcesContent":["/**\n * better-auth config factory for agent products (#188 Phase 1). Every product\n * hand-rolls the same ~70–150 line setup — drizzle adapter over the standard\n * users/sessions/accounts/verifications tables, email+password with Resend\n * reset/verification mail, env-gated GitHub/Google social providers, session\n * cookie cache, and a per-app cookie prefix — and tax additionally\n * re-implemented better-auth's cookie signing for its Tangle SSO callback.\n * `createAppAuth` owns that mechanism once and returns the configured\n * better-auth instance plus the request guards products actually use.\n *\n * Domain stays a parameter: the drizzle db + schema, email client, provider\n * credentials, and SSO store/client all come from the product. No product\n * import, no engine re-implementation — the SSO path composes the existing\n * `platform/sso` cookie minter (`createBetterAuthSessionCookieMinter`), which\n * is byte-compatible with better-auth's own `makeSignature` contract.\n *\n * better-auth is an OPTIONAL peer: only this subpath imports it, so it is\n * deliberately NOT re-exported from the root barrel.\n */\n\nimport { betterAuth, type Auth, type BetterAuthOptions, type Session, type User } from 'better-auth'\nimport { drizzleAdapter } from 'better-auth/adapters/drizzle'\nimport { createAuthGuard, type AuthGuard } from '../platform/guards'\nimport {\n createBetterAuthSessionCookieMinter,\n createTangleSsoHandlers,\n type TangleSsoAccountStore,\n type TangleSsoAuthClient,\n type TangleSsoHandlers,\n} from '../platform/sso'\n\nconst DEFAULT_STATE_COOKIE = 'tangle_sso_state'\nconst DEFAULT_SESSION_COOKIE_CACHE_SECONDS = 5 * 60\n\n/** Structural slice of a Resend-style client — no `resend` import. */\nexport interface AppAuthEmailClient {\n emails: {\n send(message: {\n from: string\n to: string\n subject: string\n html: string\n text?: string\n }): Promise<unknown>\n }\n}\n\n/** Define email configuration for app authentication including client, sender, verification, and warning options */\nexport interface AppAuthEmailConfig {\n /** A Resend-style client, or a lazy getter returning null when the API key\n * is absent (the products' dev default — mail is skipped with a warning,\n * sign-up itself must not crash). */\n resend: AppAuthEmailClient | (() => AppAuthEmailClient | null)\n /** RFC 5322 From, e.g. `'Legal Agent <noreply@legal.tangle.tools>'`. */\n from: string\n /** Send a verification email on sign-up and auto-sign-in after verifying\n * (the tax/gtm behavior). Default false (the legal behavior). */\n verifyOnSignUp?: boolean\n /** Receives the \"email client unavailable\" warning. Default console.warn. */\n warn?: (message: string) => void\n}\n\n/** Env-shaped: pass the env vars straight through; the provider is registered\n * only when BOTH values are non-empty, so unset env disables it. */\nexport interface AppAuthSocialProviderConfig {\n clientId?: string\n clientSecret?: string\n}\n\n/** Define social authentication configuration options for GitHub and Google providers */\nexport interface AppAuthSocialConfig {\n github?: AppAuthSocialProviderConfig\n google?: AppAuthSocialProviderConfig\n}\n\n/** Cross-site Tangle SSO wiring. The factory supplies the better-auth side —\n * `setSessionCookie` via `createBetterAuthSessionCookieMinter(auth)` (signed\n * `__Secure-`/prefixed cookie that `auth.api.getSession` accepts) — so the\n * product no longer touches `better-auth/crypto` itself. */\nexport interface AppAuthSsoConfig {\n /** Platform wire client (authorizeUrl + exchange). */\n client: TangleSsoAuthClient\n /** Product persistence: user upsert, session row, platform link. */\n store: TangleSsoAccountStore\n /** Absolute callback URL registered with the platform. */\n callbackUrl: string\n /** Default 'tangle_sso_state'. */\n stateCookieName?: string\n /** HMAC secret for the CSRF state cookie. Default: the auth `secret`. */\n stateSecret?: string\n /** Default: `baseURL` is https. Must match better-auth's own\n * secure-cookie decision or the cookie name lookup diverges. */\n secureCookies?: boolean\n sessionTtlSeconds?: number\n stateTtlSeconds?: number\n /** Post-login redirect fallback. Default '/app'. */\n defaultRedirectPath?: string\n /** Default: the top-level `loginPath`. */\n loginPath?: string\n /** Failure log hook (e.g. console.error). Default no-op. */\n log?: (message: string, error?: unknown) => void\n}\n\n/** Define the structure for application authentication data including users, sessions, accounts, and verifications */\nexport interface AppAuthSchema {\n users: unknown\n sessions: unknown\n accounts: unknown\n verifications: unknown\n}\n\n/** Define configuration settings for app authentication including app name, base URL, secrets, and trusted origins */\nexport interface AppAuthConfig {\n /** Product name — used in email subjects and as the cookie-prefix default. */\n appName: string\n /** Absolute origin better-auth serves from (`BETTER_AUTH_URL`). */\n baseURL: string\n /** better-auth HMAC secret. Optional only because better-auth falls back to\n * the BETTER_AUTH_SECRET env var; `sso` needs it explicitly (or\n * `sso.stateSecret`). */\n secret?: string\n trustedOrigins?: string[]\n /**\n * Session-cookie prefix. Default: slugified `appName`. A per-app prefix is\n * load-bearing, not cosmetic: the platform (id.tangle.tools) mints its own\n * better-auth cookie `Domain=.tangle.tools`-wide under the DEFAULT name, and\n * the platform's (older) cookie wins the Cookie-header order — an app on the\n * default prefix reads the platform's token, fails its own signature check,\n * and every fresh login lands back on /login.\n */\n cookiePrefix?: string\n /** Drizzle database instance; wired through better-auth's drizzle adapter\n * together with `schema`. */\n db?: unknown\n /** The product's users/sessions/accounts/verifications tables (mapped to\n * better-auth's user/session/account/verification models). */\n schema?: AppAuthSchema\n /** Drizzle dialect. Default 'sqlite' (D1). */\n provider?: 'sqlite' | 'pg' | 'mysql'\n /** Escape hatch: a pre-built better-auth database adapter (e.g.\n * `memoryAdapter` in tests). Wins over `db`/`schema`. */\n database?: BetterAuthOptions['database']\n /** Email+password sign-in. Default true (all current products enable it). */\n emailAndPassword?: boolean\n /** Reset/verification mail. Omit to disable password reset entirely. */\n email?: AppAuthEmailConfig\n social?: AppAuthSocialConfig\n /** Session cookie-cache TTL in seconds; `false` disables the cache.\n * Default 300. */\n sessionCookieCacheSeconds?: number | false\n /** Tangle cross-site SSO (start/callback handlers). */\n sso?: AppAuthSsoConfig\n /** Where guards redirect unauthenticated page requests. Default '/login'. */\n loginPath?: string\n /** Merged over the factory's `advanced` block (cookiePrefix stays unless\n * overridden here). */\n advanced?: BetterAuthOptions['advanced']\n}\n\n/** The configured better-auth instance, typed at better-auth's base surface\n * (`handler`, `api`, `$context`, `$Infer`). */\nexport type AppAuthInstance = Auth\n\n/** What `getSession`/guards resolve: better-auth's base session + user rows. */\nexport interface AppAuthSession {\n session: Session\n user: User\n}\n\n/** Define authentication guard with session retrieval and optional SSO handlers for app requests */\nexport interface AppAuth extends AuthGuard<AppAuthSession> {\n auth: AppAuthInstance\n /** `auth.api.getSession` over a `Request` — the seam the guards consume. */\n getSession(request: Request): Promise<AppAuthSession | null>\n /** Tangle SSO start/callback handlers; null unless `sso` was configured. */\n sso: TangleSsoHandlers | null\n}\n\n/** Lowercased, non-alphanumerics collapsed to '-': `'Legal Agent'` → `'legal-agent'`. */\nfunction slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\nfunction resolveEmailClient(email: AppAuthEmailConfig): AppAuthEmailClient | null {\n return typeof email.resend === 'function' ? email.resend() : email.resend\n}\n\ntype DrizzleAuthAdapter = ReturnType<ReturnType<typeof drizzleAdapter>>\n\n/** Better Auth reads adapter identity during startup, before Workers inject D1.\n * Build the Drizzle adapter on its first database operation. */\nfunction deferDrizzleAdapter(\n db: Record<string, unknown>,\n config: Parameters<typeof drizzleAdapter>[1],\n): ReturnType<typeof drizzleAdapter> {\n return (options) => {\n let adapter: DrizzleAuthAdapter | undefined\n const resolve = () => (adapter ??= drizzleAdapter(db, config)(options))\n\n return {\n id: 'drizzle',\n create: (data) => resolve().create(data),\n findOne: (data) => resolve().findOne(data),\n findMany: (data) => resolve().findMany(data),\n count: (data) => resolve().count(data),\n update: (data) => resolve().update(data),\n updateMany: (data) => resolve().updateMany(data),\n delete: (data) => resolve().delete(data),\n deleteMany: (data) => resolve().deleteMany(data),\n consumeOne: (data) => resolve().consumeOne(data),\n incrementOne: (data) => resolve().incrementOne(data),\n transaction: (callback) => resolve().transaction(callback),\n }\n }\n}\n\n/** Resend reports failures in the resolved value, not by rejecting — surface\n * them loud so better-auth's flow (and the caller's logs) see the failure. */\nasync function sendEmail(\n client: AppAuthEmailClient,\n message: { from: string; to: string; subject: string; html: string; text: string },\n): Promise<void> {\n const result = (await client.emails.send(message)) as { error?: { message?: string } | null } | null | undefined\n if (result && typeof result === 'object' && result.error) {\n throw new Error(`[app-auth] email send failed: ${result.error.message ?? 'unknown error'}`)\n }\n}\n\nfunction resolveDatabase(config: AppAuthConfig): NonNullable<BetterAuthOptions['database']> {\n if (config.database) return config.database\n if (config.db && config.schema) {\n return deferDrizzleAdapter(config.db as Record<string, unknown>, {\n provider: config.provider ?? 'sqlite',\n schema: {\n user: config.schema.users,\n session: config.schema.sessions,\n account: config.schema.accounts,\n verification: config.schema.verifications,\n } as Record<string, unknown>,\n })\n }\n throw new Error(\n 'createAppAuth requires a database: pass `db` + `schema` (drizzle) or `database` (a better-auth adapter)',\n )\n}\n\nfunction resolveSocialProviders(social: AppAuthSocialConfig | undefined): BetterAuthOptions['socialProviders'] {\n const providers: NonNullable<BetterAuthOptions['socialProviders']> = {}\n if (social?.github?.clientId && social.github.clientSecret) {\n providers.github = { clientId: social.github.clientId, clientSecret: social.github.clientSecret }\n }\n if (social?.google?.clientId && social.google.clientSecret) {\n providers.google = { clientId: social.google.clientId, clientSecret: social.google.clientSecret }\n }\n return Object.keys(providers).length > 0 ? providers : undefined\n}\n\nfunction emailAndPasswordOptions(config: AppAuthConfig): BetterAuthOptions['emailAndPassword'] {\n const email = config.email\n if (!email) return { enabled: true }\n const warn = email.warn ?? ((message: string) => console.warn(message))\n return {\n enabled: true,\n sendResetPassword: async ({ user, url }) => {\n const client = resolveEmailClient(email)\n if (!client) {\n warn('[app-auth] email client unavailable — password reset email not sent')\n return\n }\n await sendEmail(client, {\n from: email.from,\n to: user.email,\n subject: 'Reset your password',\n html: `<p>Click the link below to reset your password:</p><p><a href=\"${url}\">${url}</a></p><p>This link expires in 1 hour.</p>`,\n text: `Reset your password:\\n\\n${url}\\n\\nThis link expires in 1 hour.`,\n })\n },\n }\n}\n\nfunction emailVerificationOptions(config: AppAuthConfig): BetterAuthOptions['emailVerification'] {\n const email = config.email\n if (!email?.verifyOnSignUp) return undefined\n const warn = email.warn ?? ((message: string) => console.warn(message))\n return {\n sendOnSignUp: true,\n autoSignInAfterVerification: true,\n sendVerificationEmail: async ({ user, url }) => {\n const client = resolveEmailClient(email)\n if (!client) {\n warn('[app-auth] email client unavailable — verification email not sent')\n return\n }\n await sendEmail(client, {\n from: email.from,\n to: user.email,\n subject: `Verify your ${config.appName} email`,\n html: `<p>Verify your email to finish accessing ${config.appName}:</p><p><a href=\"${url}\">${url}</a></p><p>This link expires in 1 hour.</p>`,\n text: `Verify your email to finish accessing ${config.appName}:\\n\\n${url}\\n\\nThis link expires in 1 hour.`,\n })\n },\n }\n}\n\n/**\n * Build the product's better-auth instance plus the request-boundary helpers:\n * `getSession` (Request → session|null), the `createAuthGuard` quartet\n * (`requireUser` 302, `requireApiUser` JSON 401, `requireSession`,\n * `getOptionalSession`), and — when `sso` is configured — the Tangle SSO\n * start/callback handlers with the session cookie minted through better-auth's\n * own name/attributes/signing (no `better-auth/crypto` in product code).\n */\nexport function createAppAuth(config: AppAuthConfig): AppAuth {\n if (!config.appName) throw new Error('createAppAuth: appName is required')\n if (!config.baseURL) throw new Error('createAppAuth: baseURL is required')\n\n const cookiePrefix = config.cookiePrefix ?? slugify(config.appName)\n if (!cookiePrefix) throw new Error('createAppAuth: cookiePrefix (or a slugifiable appName) is required')\n\n const socialProviders = resolveSocialProviders(config.social)\n const options: BetterAuthOptions = {\n appName: config.appName,\n baseURL: config.baseURL,\n ...(config.secret ? { secret: config.secret } : {}),\n ...(config.trustedOrigins ? { trustedOrigins: config.trustedOrigins } : {}),\n database: resolveDatabase(config),\n ...(config.emailAndPassword === false ? {} : { emailAndPassword: emailAndPasswordOptions(config) }),\n ...(config.email?.verifyOnSignUp ? { emailVerification: emailVerificationOptions(config) } : {}),\n ...(socialProviders ? { socialProviders } : {}),\n ...(config.sessionCookieCacheSeconds === false\n ? {}\n : {\n session: {\n cookieCache: {\n enabled: true,\n maxAge: config.sessionCookieCacheSeconds ?? DEFAULT_SESSION_COOKIE_CACHE_SECONDS,\n },\n },\n }),\n advanced: { cookiePrefix, ...config.advanced },\n }\n\n const auth: AppAuthInstance = betterAuth(options)\n\n const getSession = async (request: Request): Promise<AppAuthSession | null> => {\n const session = await auth.api.getSession({ headers: request.headers })\n return (session as AppAuthSession | null) ?? null\n }\n\n const loginPath = config.loginPath ?? '/login'\n const guard = createAuthGuard<AppAuthSession>({ getSession, loginPath })\n\n let sso: TangleSsoHandlers | null = null\n if (config.sso) {\n const stateSecret = config.sso.stateSecret ?? config.secret\n if (!stateSecret) {\n throw new Error(\n 'createAppAuth: sso requires `secret` (or sso.stateSecret) — the signed-state CSRF cookie needs an HMAC secret',\n )\n }\n sso = createTangleSsoHandlers({\n auth: config.sso.client,\n store: config.sso.store,\n stateSecret,\n callbackUrl: config.sso.callbackUrl,\n stateCookieName: config.sso.stateCookieName ?? DEFAULT_STATE_COOKIE,\n setSessionCookie: createBetterAuthSessionCookieMinter(auth),\n secureCookies: config.sso.secureCookies ?? config.baseURL.startsWith('https:'),\n ...(config.sso.sessionTtlSeconds !== undefined ? { sessionTtlSeconds: config.sso.sessionTtlSeconds } : {}),\n ...(config.sso.stateTtlSeconds !== undefined ? { stateTtlSeconds: config.sso.stateTtlSeconds } : {}),\n ...(config.sso.defaultRedirectPath ? { defaultRedirectPath: config.sso.defaultRedirectPath } : {}),\n loginPath: config.sso.loginPath ?? loginPath,\n ...(config.sso.log ? { log: config.sso.log } : {}),\n })\n }\n\n return { auth, getSession, ...guard, sso }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/app-auth/index.ts"],"sourcesContent":["/**\n * better-auth config factory for agent products (#188 Phase 1). Every product\n * hand-rolls the same ~70–150 line setup — drizzle adapter over the standard\n * users/sessions/accounts/verifications tables, email+password with Resend\n * reset/verification mail, env-gated GitHub/Google social providers, session\n * cookie cache, and a per-app cookie prefix — and tax additionally\n * re-implemented better-auth's cookie signing for its Tangle SSO callback.\n * `createAppAuth` owns that mechanism once and returns the configured\n * better-auth instance plus the request guards products actually use.\n *\n * Domain stays a parameter: the drizzle db + schema, email client, provider\n * credentials, and SSO store/client all come from the product. No product\n * import, no engine re-implementation — the SSO path composes the existing\n * `platform/sso` cookie minter (`createBetterAuthSessionCookieMinter`), which\n * is byte-compatible with better-auth's own `makeSignature` contract.\n *\n * better-auth is an OPTIONAL peer: only this subpath imports it, so it is\n * deliberately NOT re-exported from the root barrel.\n */\n\nimport { betterAuth, type Auth, type BetterAuthOptions, type Session, type User } from 'better-auth'\nimport { drizzleAdapter } from 'better-auth/adapters/drizzle'\nimport { createAuthGuard, type AuthGuard } from '../platform/guards'\nimport {\n createBetterAuthSessionCookieMinter,\n createTangleSsoHandlers,\n type TangleSsoAccountStore,\n type TangleSsoAuthClient,\n type TangleSsoHandlers,\n} from '../platform/sso'\n\nconst DEFAULT_STATE_COOKIE = 'tangle_sso_state'\nconst DEFAULT_SESSION_COOKIE_CACHE_SECONDS = 5 * 60\n\n/** Structural slice of a Resend-style client — no `resend` import. */\nexport interface AppAuthEmailClient {\n emails: {\n send(message: {\n from: string\n to: string\n subject: string\n html: string\n text?: string\n }): Promise<unknown>\n }\n}\n\n/** Define email configuration for app authentication including client, sender, verification, and warning options */\nexport interface AppAuthEmailConfig {\n /** A Resend-style client, or a lazy getter returning null when the API key\n * is absent (the products' dev default — mail is skipped with a warning,\n * sign-up itself must not crash). */\n resend: AppAuthEmailClient | (() => AppAuthEmailClient | null)\n /** RFC 5322 From, e.g. `'Legal Agent <noreply@legal.tangle.tools>'`. */\n from: string\n /** Send a verification email on sign-up and auto-sign-in after verifying\n * (the tax/gtm behavior). Default false (the legal behavior). */\n verifyOnSignUp?: boolean\n /** Receives the \"email client unavailable\" warning. Default console.warn. */\n warn?: (message: string) => void\n}\n\n/** Env-shaped: pass the env vars straight through; the provider is registered\n * only when BOTH values are non-empty, so unset env disables it. */\nexport interface AppAuthSocialProviderConfig {\n clientId?: string\n clientSecret?: string\n}\n\n/** Define social authentication configuration options for GitHub and Google providers */\nexport interface AppAuthSocialConfig {\n github?: AppAuthSocialProviderConfig\n google?: AppAuthSocialProviderConfig\n}\n\n/** Cross-site Tangle SSO wiring. The factory supplies the better-auth side —\n * `setSessionCookie` via `createBetterAuthSessionCookieMinter(auth)` (signed\n * `__Secure-`/prefixed cookie that `auth.api.getSession` accepts) — so the\n * product no longer touches `better-auth/crypto` itself. */\nexport interface AppAuthSsoConfig {\n /** Platform wire client (authorizeUrl + exchange). */\n client: TangleSsoAuthClient\n /** Product persistence: user upsert, session row, platform link. */\n store: TangleSsoAccountStore\n /** Absolute callback URL registered with the platform. */\n callbackUrl: string\n /** Default 'tangle_sso_state'. */\n stateCookieName?: string\n /** HMAC secret for the CSRF state cookie. Default: the auth `secret`. */\n stateSecret?: string\n /** Default: `baseURL` is https. Must match better-auth's own\n * secure-cookie decision or the cookie name lookup diverges. */\n secureCookies?: boolean\n sessionTtlSeconds?: number\n stateTtlSeconds?: number\n /** Post-login redirect fallback. Default '/app'. */\n defaultRedirectPath?: string\n /** Default: the top-level `loginPath`. */\n loginPath?: string\n /** Failure log hook (e.g. console.error). Default no-op. */\n log?: (message: string, error?: unknown) => void\n}\n\n/** Define the structure for application authentication data including users, sessions, accounts, and verifications */\nexport interface AppAuthSchema {\n users: unknown\n sessions: unknown\n accounts: unknown\n verifications: unknown\n}\n\n/** Define configuration settings for app authentication including app name, base URL, secrets, and trusted origins */\nexport interface AppAuthConfig {\n /** Product name — used in email subjects and as the cookie-prefix default. */\n appName: string\n /** Absolute origin better-auth serves from (`BETTER_AUTH_URL`). */\n baseURL: string\n /** better-auth HMAC secret. Optional only because better-auth falls back to\n * the BETTER_AUTH_SECRET env var; `sso` needs it explicitly (or\n * `sso.stateSecret`). */\n secret?: string\n trustedOrigins?: string[]\n /**\n * Session-cookie prefix. Default: slugified `appName`. A per-app prefix is\n * load-bearing, not cosmetic: the platform (id.tangle.tools) mints its own\n * better-auth cookie `Domain=.tangle.tools`-wide under the DEFAULT name, and\n * the platform's (older) cookie wins the Cookie-header order — an app on the\n * default prefix reads the platform's token, fails its own signature check,\n * and every fresh login lands back on /login.\n */\n cookiePrefix?: string\n /** Drizzle database instance; wired through better-auth's drizzle adapter\n * together with `schema`. */\n db?: unknown\n /** The product's users/sessions/accounts/verifications tables (mapped to\n * better-auth's user/session/account/verification models). */\n schema?: AppAuthSchema\n /** Drizzle dialect. Default 'sqlite' (D1). */\n provider?: 'sqlite' | 'pg' | 'mysql'\n /** Escape hatch: a pre-built better-auth database adapter (e.g.\n * `memoryAdapter` in tests). Wins over `db`/`schema`. */\n database?: BetterAuthOptions['database']\n /** Email+password sign-in. Default true (all current products enable it). */\n emailAndPassword?: boolean\n /** Reset/verification mail. Omit to disable password reset entirely. */\n email?: AppAuthEmailConfig\n social?: AppAuthSocialConfig\n /** Session cookie-cache TTL in seconds; `false` disables the cache.\n * Default 300. */\n sessionCookieCacheSeconds?: number | false\n /** Tangle cross-site SSO (start/callback handlers). */\n sso?: AppAuthSsoConfig\n /** Where guards redirect unauthenticated page requests. Default '/login'. */\n loginPath?: string\n /** Merged over the factory's `advanced` block (cookiePrefix stays unless\n * overridden here). */\n advanced?: BetterAuthOptions['advanced']\n}\n\n/** The configured better-auth instance, typed at better-auth's base surface\n * (`handler`, `api`, `$context`, `$Infer`). */\nexport type AppAuthInstance = Auth\n\n/** What `getSession`/guards resolve: better-auth's base session + user rows. */\nexport interface AppAuthSession {\n session: Session\n user: User\n}\n\n/** Define authentication guard with session retrieval and optional SSO handlers for app requests */\nexport interface AppAuth extends AuthGuard<AppAuthSession> {\n auth: AppAuthInstance\n /** `auth.api.getSession` over a `Request` — the seam the guards consume. */\n getSession(request: Request): Promise<AppAuthSession | null>\n /** Tangle SSO start/callback handlers; null unless `sso` was configured. */\n sso: TangleSsoHandlers | null\n}\n\n/** Lowercased, non-alphanumerics collapsed to '-': `'Legal Agent'` → `'legal-agent'`. */\nfunction slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\nfunction resolveEmailClient(email: AppAuthEmailConfig): AppAuthEmailClient | null {\n return typeof email.resend === 'function' ? email.resend() : email.resend\n}\n\ntype DrizzleAuthAdapter = ReturnType<ReturnType<typeof drizzleAdapter>>\n\n/** Better Auth reads adapter identity during startup, before Workers inject D1.\n * Build the Drizzle adapter on its first database operation. */\nfunction deferDrizzleAdapter(\n db: Record<string, unknown>,\n config: Parameters<typeof drizzleAdapter>[1],\n): ReturnType<typeof drizzleAdapter> {\n return (options) => {\n let adapter: DrizzleAuthAdapter | undefined\n const resolve = () => (adapter ??= drizzleAdapter(db, config)(options))\n\n return {\n id: 'drizzle',\n create: (data) => resolve().create(data),\n findOne: (data) => resolve().findOne(data),\n findMany: (data) => resolve().findMany(data),\n count: (data) => resolve().count(data),\n update: (data) => resolve().update(data),\n updateMany: (data) => resolve().updateMany(data),\n delete: (data) => resolve().delete(data),\n deleteMany: (data) => resolve().deleteMany(data),\n consumeOne: (data) => resolve().consumeOne(data),\n incrementOne: (data) => resolve().incrementOne(data),\n transaction: (callback) => resolve().transaction(callback),\n }\n }\n}\n\n/** Resend reports failures in the resolved value, not by rejecting — surface\n * them loud so better-auth's flow (and the caller's logs) see the failure. */\nasync function sendEmail(\n client: AppAuthEmailClient,\n message: { from: string; to: string; subject: string; html: string; text: string },\n): Promise<void> {\n const result = (await client.emails.send(message)) as { error?: { message?: string } | null } | null | undefined\n if (result && typeof result === 'object' && result.error) {\n throw new Error(`[app-auth] email send failed: ${result.error.message ?? 'unknown error'}`)\n }\n}\n\nfunction resolveDatabase(config: AppAuthConfig): NonNullable<BetterAuthOptions['database']> {\n if (config.database) return config.database\n if (config.db && config.schema) {\n return deferDrizzleAdapter(config.db as Record<string, unknown>, {\n provider: config.provider ?? 'sqlite',\n schema: {\n user: config.schema.users,\n session: config.schema.sessions,\n account: config.schema.accounts,\n verification: config.schema.verifications,\n } as Record<string, unknown>,\n })\n }\n throw new Error(\n 'createAppAuth requires a database: pass `db` + `schema` (drizzle) or `database` (a better-auth adapter)',\n )\n}\n\nfunction resolveSocialProviders(social: AppAuthSocialConfig | undefined): BetterAuthOptions['socialProviders'] {\n const providers: NonNullable<BetterAuthOptions['socialProviders']> = {}\n if (social?.github?.clientId && social.github.clientSecret) {\n providers.github = { clientId: social.github.clientId, clientSecret: social.github.clientSecret }\n }\n if (social?.google?.clientId && social.google.clientSecret) {\n providers.google = { clientId: social.google.clientId, clientSecret: social.google.clientSecret }\n }\n return Object.keys(providers).length > 0 ? providers : undefined\n}\n\nfunction emailAndPasswordOptions(config: AppAuthConfig): BetterAuthOptions['emailAndPassword'] {\n const email = config.email\n if (!email) return { enabled: true }\n const warn = email.warn ?? ((message: string) => console.warn(message))\n return {\n enabled: true,\n sendResetPassword: async ({ user, url }) => {\n const client = resolveEmailClient(email)\n if (!client) {\n warn('[app-auth] email client unavailable — password reset email not sent')\n return\n }\n await sendEmail(client, {\n from: email.from,\n to: user.email,\n subject: 'Reset your password',\n html: `<p>Click the link below to reset your password:</p><p><a href=\"${url}\">${url}</a></p><p>This link expires in 1 hour.</p>`,\n text: `Reset your password:\\n\\n${url}\\n\\nThis link expires in 1 hour.`,\n })\n },\n }\n}\n\nfunction emailVerificationOptions(config: AppAuthConfig): BetterAuthOptions['emailVerification'] {\n const email = config.email\n if (!email?.verifyOnSignUp) return undefined\n const warn = email.warn ?? ((message: string) => console.warn(message))\n return {\n sendOnSignUp: true,\n autoSignInAfterVerification: true,\n sendVerificationEmail: async ({ user, url }) => {\n const client = resolveEmailClient(email)\n if (!client) {\n warn('[app-auth] email client unavailable — verification email not sent')\n return\n }\n await sendEmail(client, {\n from: email.from,\n to: user.email,\n subject: `Verify your ${config.appName} email`,\n html: `<p>Verify your email to finish accessing ${config.appName}:</p><p><a href=\"${url}\">${url}</a></p><p>This link expires in 1 hour.</p>`,\n text: `Verify your email to finish accessing ${config.appName}:\\n\\n${url}\\n\\nThis link expires in 1 hour.`,\n })\n },\n }\n}\n\n/**\n * Build the product's better-auth instance plus the request-boundary helpers:\n * `getSession` (Request → session|null), the `createAuthGuard` quartet\n * (`requireUser` 302, `requireApiUser` JSON 401, `requireSession`,\n * `getOptionalSession`), and — when `sso` is configured — the Tangle SSO\n * start/callback handlers with the session cookie minted through better-auth's\n * own name/attributes/signing (no `better-auth/crypto` in product code).\n */\nexport function createAppAuth(config: AppAuthConfig): AppAuth {\n if (!config.appName) throw new Error('createAppAuth: appName is required')\n if (!config.baseURL) throw new Error('createAppAuth: baseURL is required')\n\n const cookiePrefix = config.cookiePrefix ?? slugify(config.appName)\n if (!cookiePrefix) throw new Error('createAppAuth: cookiePrefix (or a slugifiable appName) is required')\n\n const socialProviders = resolveSocialProviders(config.social)\n const options: BetterAuthOptions = {\n appName: config.appName,\n baseURL: config.baseURL,\n ...(config.secret ? { secret: config.secret } : {}),\n ...(config.trustedOrigins ? { trustedOrigins: config.trustedOrigins } : {}),\n database: resolveDatabase(config),\n ...(config.emailAndPassword === false ? {} : { emailAndPassword: emailAndPasswordOptions(config) }),\n ...(config.email?.verifyOnSignUp ? { emailVerification: emailVerificationOptions(config) } : {}),\n ...(socialProviders ? { socialProviders } : {}),\n ...(config.sessionCookieCacheSeconds === false\n ? {}\n : {\n session: {\n cookieCache: {\n enabled: true,\n maxAge: config.sessionCookieCacheSeconds ?? DEFAULT_SESSION_COOKIE_CACHE_SECONDS,\n },\n },\n }),\n advanced: { cookiePrefix, ...config.advanced },\n }\n\n const auth: AppAuthInstance = betterAuth(options)\n\n const getSession = async (request: Request): Promise<AppAuthSession | null> => {\n const session = await auth.api.getSession({ headers: request.headers })\n return (session as AppAuthSession | null) ?? null\n }\n\n const loginPath = config.loginPath ?? '/login'\n const guard = createAuthGuard<AppAuthSession>({ getSession, loginPath })\n\n let sso: TangleSsoHandlers | null = null\n if (config.sso) {\n const stateSecret = config.sso.stateSecret ?? config.secret\n if (!stateSecret) {\n throw new Error(\n 'createAppAuth: sso requires `secret` (or sso.stateSecret) — the signed-state CSRF cookie needs an HMAC secret',\n )\n }\n sso = createTangleSsoHandlers({\n auth: config.sso.client,\n store: config.sso.store,\n stateSecret,\n callbackUrl: config.sso.callbackUrl,\n stateCookieName: config.sso.stateCookieName ?? DEFAULT_STATE_COOKIE,\n setSessionCookie: createBetterAuthSessionCookieMinter(auth),\n secureCookies: config.sso.secureCookies ?? config.baseURL.startsWith('https:'),\n ...(config.sso.sessionTtlSeconds !== undefined ? { sessionTtlSeconds: config.sso.sessionTtlSeconds } : {}),\n ...(config.sso.stateTtlSeconds !== undefined ? { stateTtlSeconds: config.sso.stateTtlSeconds } : {}),\n ...(config.sso.defaultRedirectPath ? { defaultRedirectPath: config.sso.defaultRedirectPath } : {}),\n loginPath: config.sso.loginPath ?? loginPath,\n ...(config.sso.log ? { log: config.sso.log } : {}),\n })\n }\n\n return { auth, getSession, ...guard, sso }\n}\n"],"mappings":";;;;;;;;;;AAoBA,SAAS,kBAA8E;AACvF,SAAS,sBAAsB;AAU/B,IAAM,uBAAuB;AAC7B,IAAM,uCAAuC,IAAI;AAmJjD,SAAS,QAAQ,MAAsB;AACrC,SAAO,KACJ,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AAC3B;AAEA,SAAS,mBAAmB,OAAsD;AAChF,SAAO,OAAO,MAAM,WAAW,aAAa,MAAM,OAAO,IAAI,MAAM;AACrE;AAMA,SAAS,oBACP,IACA,QACmC;AACnC,SAAO,CAAC,YAAY;AAClB,QAAI;AACJ,UAAM,UAAU,MAAO,YAAY,eAAe,IAAI,MAAM,EAAE,OAAO;AAErE,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ,CAAC,SAAS,QAAQ,EAAE,OAAO,IAAI;AAAA,MACvC,SAAS,CAAC,SAAS,QAAQ,EAAE,QAAQ,IAAI;AAAA,MACzC,UAAU,CAAC,SAAS,QAAQ,EAAE,SAAS,IAAI;AAAA,MAC3C,OAAO,CAAC,SAAS,QAAQ,EAAE,MAAM,IAAI;AAAA,MACrC,QAAQ,CAAC,SAAS,QAAQ,EAAE,OAAO,IAAI;AAAA,MACvC,YAAY,CAAC,SAAS,QAAQ,EAAE,WAAW,IAAI;AAAA,MAC/C,QAAQ,CAAC,SAAS,QAAQ,EAAE,OAAO,IAAI;AAAA,MACvC,YAAY,CAAC,SAAS,QAAQ,EAAE,WAAW,IAAI;AAAA,MAC/C,YAAY,CAAC,SAAS,QAAQ,EAAE,WAAW,IAAI;AAAA,MAC/C,cAAc,CAAC,SAAS,QAAQ,EAAE,aAAa,IAAI;AAAA,MACnD,aAAa,CAAC,aAAa,QAAQ,EAAE,YAAY,QAAQ;AAAA,IAC3D;AAAA,EACF;AACF;AAIA,eAAe,UACb,QACA,SACe;AACf,QAAM,SAAU,MAAM,OAAO,OAAO,KAAK,OAAO;AAChD,MAAI,UAAU,OAAO,WAAW,YAAY,OAAO,OAAO;AACxD,UAAM,IAAI,MAAM,iCAAiC,OAAO,MAAM,WAAW,eAAe,EAAE;AAAA,EAC5F;AACF;AAEA,SAAS,gBAAgB,QAAmE;AAC1F,MAAI,OAAO,SAAU,QAAO,OAAO;AACnC,MAAI,OAAO,MAAM,OAAO,QAAQ;AAC9B,WAAO,oBAAoB,OAAO,IAA+B;AAAA,MAC/D,UAAU,OAAO,YAAY;AAAA,MAC7B,QAAQ;AAAA,QACN,MAAM,OAAO,OAAO;AAAA,QACpB,SAAS,OAAO,OAAO;AAAA,QACvB,SAAS,OAAO,OAAO;AAAA,QACvB,cAAc,OAAO,OAAO;AAAA,MAC9B;AAAA,IACF,CAAC;AAAA,EACH;AACA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAEA,SAAS,uBAAuB,QAA+E;AAC7G,QAAM,YAA+D,CAAC;AACtE,MAAI,QAAQ,QAAQ,YAAY,OAAO,OAAO,cAAc;AAC1D,cAAU,SAAS,EAAE,UAAU,OAAO,OAAO,UAAU,cAAc,OAAO,OAAO,aAAa;AAAA,EAClG;AACA,MAAI,QAAQ,QAAQ,YAAY,OAAO,OAAO,cAAc;AAC1D,cAAU,SAAS,EAAE,UAAU,OAAO,OAAO,UAAU,cAAc,OAAO,OAAO,aAAa;AAAA,EAClG;AACA,SAAO,OAAO,KAAK,SAAS,EAAE,SAAS,IAAI,YAAY;AACzD;AAEA,SAAS,wBAAwB,QAA8D;AAC7F,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAO,QAAO,EAAE,SAAS,KAAK;AACnC,QAAM,OAAO,MAAM,SAAS,CAAC,YAAoB,QAAQ,KAAK,OAAO;AACrE,SAAO;AAAA,IACL,SAAS;AAAA,IACT,mBAAmB,OAAO,EAAE,MAAM,IAAI,MAAM;AAC1C,YAAM,SAAS,mBAAmB,KAAK;AACvC,UAAI,CAAC,QAAQ;AACX,aAAK,0EAAqE;AAC1E;AAAA,MACF;AACA,YAAM,UAAU,QAAQ;AAAA,QACtB,MAAM,MAAM;AAAA,QACZ,IAAI,KAAK;AAAA,QACT,SAAS;AAAA,QACT,MAAM,kEAAkE,GAAG,KAAK,GAAG;AAAA,QACnF,MAAM;AAAA;AAAA,EAA2B,GAAG;AAAA;AAAA;AAAA,MACtC,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,SAAS,yBAAyB,QAA+D;AAC/F,QAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,OAAO,eAAgB,QAAO;AACnC,QAAM,OAAO,MAAM,SAAS,CAAC,YAAoB,QAAQ,KAAK,OAAO;AACrE,SAAO;AAAA,IACL,cAAc;AAAA,IACd,6BAA6B;AAAA,IAC7B,uBAAuB,OAAO,EAAE,MAAM,IAAI,MAAM;AAC9C,YAAM,SAAS,mBAAmB,KAAK;AACvC,UAAI,CAAC,QAAQ;AACX,aAAK,wEAAmE;AACxE;AAAA,MACF;AACA,YAAM,UAAU,QAAQ;AAAA,QACtB,MAAM,MAAM;AAAA,QACZ,IAAI,KAAK;AAAA,QACT,SAAS,eAAe,OAAO,OAAO;AAAA,QACtC,MAAM,4CAA4C,OAAO,OAAO,oBAAoB,GAAG,KAAK,GAAG;AAAA,QAC/F,MAAM,yCAAyC,OAAO,OAAO;AAAA;AAAA,EAAQ,GAAG;AAAA;AAAA;AAAA,MAC1E,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAUO,SAAS,cAAc,QAAgC;AAC5D,MAAI,CAAC,OAAO,QAAS,OAAM,IAAI,MAAM,oCAAoC;AACzE,MAAI,CAAC,OAAO,QAAS,OAAM,IAAI,MAAM,oCAAoC;AAEzE,QAAM,eAAe,OAAO,gBAAgB,QAAQ,OAAO,OAAO;AAClE,MAAI,CAAC,aAAc,OAAM,IAAI,MAAM,oEAAoE;AAEvG,QAAM,kBAAkB,uBAAuB,OAAO,MAAM;AAC5D,QAAM,UAA6B;AAAA,IACjC,SAAS,OAAO;AAAA,IAChB,SAAS,OAAO;AAAA,IAChB,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA,IACjD,GAAI,OAAO,iBAAiB,EAAE,gBAAgB,OAAO,eAAe,IAAI,CAAC;AAAA,IACzE,UAAU,gBAAgB,MAAM;AAAA,IAChC,GAAI,OAAO,qBAAqB,QAAQ,CAAC,IAAI,EAAE,kBAAkB,wBAAwB,MAAM,EAAE;AAAA,IACjG,GAAI,OAAO,OAAO,iBAAiB,EAAE,mBAAmB,yBAAyB,MAAM,EAAE,IAAI,CAAC;AAAA,IAC9F,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,IAC7C,GAAI,OAAO,8BAA8B,QACrC,CAAC,IACD;AAAA,MACE,SAAS;AAAA,QACP,aAAa;AAAA,UACX,SAAS;AAAA,UACT,QAAQ,OAAO,6BAA6B;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAAA,IACJ,UAAU,EAAE,cAAc,GAAG,OAAO,SAAS;AAAA,EAC/C;AAEA,QAAM,OAAwB,WAAW,OAAO;AAEhD,QAAM,aAAa,OAAO,YAAqD;AAC7E,UAAM,UAAU,MAAM,KAAK,IAAI,WAAW,EAAE,SAAS,QAAQ,QAAQ,CAAC;AACtE,WAAQ,WAAqC;AAAA,EAC/C;AAEA,QAAM,YAAY,OAAO,aAAa;AACtC,QAAM,QAAQ,gBAAgC,EAAE,YAAY,UAAU,CAAC;AAEvE,MAAI,MAAgC;AACpC,MAAI,OAAO,KAAK;AACd,UAAM,cAAc,OAAO,IAAI,eAAe,OAAO;AACrD,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,wBAAwB;AAAA,MAC5B,MAAM,OAAO,IAAI;AAAA,MACjB,OAAO,OAAO,IAAI;AAAA,MAClB;AAAA,MACA,aAAa,OAAO,IAAI;AAAA,MACxB,iBAAiB,OAAO,IAAI,mBAAmB;AAAA,MAC/C,kBAAkB,oCAAoC,IAAI;AAAA,MAC1D,eAAe,OAAO,IAAI,iBAAiB,OAAO,QAAQ,WAAW,QAAQ;AAAA,MAC7E,GAAI,OAAO,IAAI,sBAAsB,SAAY,EAAE,mBAAmB,OAAO,IAAI,kBAAkB,IAAI,CAAC;AAAA,MACxG,GAAI,OAAO,IAAI,oBAAoB,SAAY,EAAE,iBAAiB,OAAO,IAAI,gBAAgB,IAAI,CAAC;AAAA,MAClG,GAAI,OAAO,IAAI,sBAAsB,EAAE,qBAAqB,OAAO,IAAI,oBAAoB,IAAI,CAAC;AAAA,MAChG,WAAW,OAAO,IAAI,aAAa;AAAA,MACnC,GAAI,OAAO,IAAI,MAAM,EAAE,KAAK,OAAO,IAAI,IAAI,IAAI,CAAC;AAAA,IAClD,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,MAAM,YAAY,GAAG,OAAO,IAAI;AAC3C;","names":[]}
|
package/dist/assistant/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ChatEmptyState,
|
|
3
3
|
ChatMessages
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-H6R3VYAZ.js";
|
|
5
5
|
import "../chunk-F32T3DRJ.js";
|
|
6
6
|
import "../chunk-3HUFJ5LO.js";
|
|
7
7
|
import {
|
|
@@ -12,20 +12,21 @@ import "../chunk-ENLRJYVW.js";
|
|
|
12
12
|
import "../chunk-GEYACSFW.js";
|
|
13
13
|
import {
|
|
14
14
|
ChatComposer
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-TNWQA5XJ.js";
|
|
16
16
|
import "../chunk-L7MB2LLM.js";
|
|
17
17
|
import {
|
|
18
18
|
ModelPicker
|
|
19
19
|
} from "../chunk-4I76LTZS.js";
|
|
20
20
|
import "../chunk-SJWIZT7B.js";
|
|
21
21
|
import "../chunk-BATKJP3P.js";
|
|
22
|
-
import "../chunk-
|
|
23
|
-
import "../chunk-
|
|
22
|
+
import "../chunk-FQYAJYPW.js";
|
|
23
|
+
import "../chunk-NU7QSZBR.js";
|
|
24
24
|
import "../chunk-MCYJON3F.js";
|
|
25
25
|
import "../chunk-OU3VTK3I.js";
|
|
26
|
-
import "../chunk-
|
|
26
|
+
import "../chunk-4PZE7XAM.js";
|
|
27
27
|
import "../chunk-ZVEEWGDK.js";
|
|
28
|
-
import "../chunk-
|
|
28
|
+
import "../chunk-X47R2IVO.js";
|
|
29
|
+
import "../chunk-TXD5HXLE.js";
|
|
29
30
|
import "../chunk-ZMMIQOFI.js";
|
|
30
31
|
import "../chunk-M3K2HVQD.js";
|
|
31
32
|
import "../chunk-YJMCRXQQ.js";
|