mirror of
https://github.com/eliasstepanik/core.git
synced 2026-01-11 09:48:27 +00:00
Fix: authentication and ingest API
This commit is contained in:
parent
33eae2619a
commit
941ce8e4fa
@ -11,6 +11,7 @@
|
|||||||
C.O.R.E lets you create a private, portable, open-source memory space for LLMs, all stored locally for full data control. You decide what to share or connect with other tools, managing exactly what gets recalled and where.
|
C.O.R.E lets you create a private, portable, open-source memory space for LLMs, all stored locally for full data control. You decide what to share or connect with other tools, managing exactly what gets recalled and where.
|
||||||
|
|
||||||
C.O.R.E is built for two reasons:
|
C.O.R.E is built for two reasons:
|
||||||
|
|
||||||
1. To give you complete ownership of your memory, stored locally and accessible across any app needing LLM context.
|
1. To give you complete ownership of your memory, stored locally and accessible across any app needing LLM context.
|
||||||
2. To help SOL (your AI assistant) access your context, facts, and preferences for more relevant and personalized responses.
|
2. To help SOL (your AI assistant) access your context, facts, and preferences for more relevant and personalized responses.
|
||||||
|
|
||||||
@ -25,11 +26,11 @@ C.O.R.E supports **temporal reasoning**, **relational memory**, and **traceabili
|
|||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
1. Docker
|
1. Docker
|
||||||
2. OpenAI API Key
|
2. OpenAI API Key
|
||||||
|
|
||||||
|
### Run C.O.R.E locally by
|
||||||
### Run C.O.R.E locally by
|
|
||||||
|
|
||||||
1. **Copy Environment Variables**
|
1. **Copy Environment Variables**
|
||||||
|
|
||||||
@ -97,7 +98,6 @@ You can also interact with C.O.R.E. programmatically via its APIs.
|
|||||||
{
|
{
|
||||||
"episodeBody": "I love playing badminton",
|
"episodeBody": "I love playing badminton",
|
||||||
"referenceTime": "2024-06-01T12:00:00Z",
|
"referenceTime": "2024-06-01T12:00:00Z",
|
||||||
"type": "Conversation", // or "Text"
|
|
||||||
"source": "user", // Which tool or user is ingesting
|
"source": "user", // Which tool or user is ingesting
|
||||||
"spaceId": "your-space-id", // optional, for multiple spaces
|
"spaceId": "your-space-id", // optional, for multiple spaces
|
||||||
"sessionId": "your-session-id" // optional
|
"sessionId": "your-session-id" // optional
|
||||||
|
|||||||
@ -76,9 +76,10 @@ export function getUserQueue(userId: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const IngestBodyRequest = z.object({
|
export const IngestBodyRequest = z.object({
|
||||||
|
name: z.string(),
|
||||||
episodeBody: z.string(),
|
episodeBody: z.string(),
|
||||||
referenceTime: z.string(),
|
referenceTime: z.string(),
|
||||||
type: z.enum([EpisodeType.Conversation, EpisodeType.Text]), // Assuming these are the EpisodeType values
|
metadata: z.record(z.union([z.string(), z.number()])),
|
||||||
source: z.string(),
|
source: z.string(),
|
||||||
spaceId: z.string().optional(),
|
spaceId: z.string().optional(),
|
||||||
sessionId: z.string().optional(),
|
sessionId: z.string().optional(),
|
||||||
|
|||||||
@ -1,10 +1,17 @@
|
|||||||
import {
|
import {
|
||||||
|
createCookie,
|
||||||
redirect,
|
redirect,
|
||||||
type ActionFunctionArgs,
|
type ActionFunctionArgs,
|
||||||
type LoaderFunctionArgs,
|
type LoaderFunctionArgs,
|
||||||
type MetaFunction,
|
type MetaFunction,
|
||||||
} from "@remix-run/node";
|
} from "@remix-run/node";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "~/components/ui/card";
|
||||||
import { Form, useNavigation } from "@remix-run/react";
|
import { Form, useNavigation } from "@remix-run/react";
|
||||||
import { Inbox, Loader, Mail } from "lucide-react";
|
import { Inbox, Loader, Mail } from "lucide-react";
|
||||||
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
import { typedjson, useTypedLoaderData } from "remix-typedjson";
|
||||||
@ -16,8 +23,7 @@ import { FormButtons } from "~/components/ui/FormButtons";
|
|||||||
import { Header1 } from "~/components/ui/Headers";
|
import { Header1 } from "~/components/ui/Headers";
|
||||||
import { Input } from "~/components/ui/input";
|
import { Input } from "~/components/ui/input";
|
||||||
import { Paragraph } from "~/components/ui/Paragraph";
|
import { Paragraph } from "~/components/ui/Paragraph";
|
||||||
import { TextLink } from "~/components/ui/TextLink";
|
import { Cookie } from "@mjackson/headers";
|
||||||
|
|
||||||
import { authenticator } from "~/services/auth.server";
|
import { authenticator } from "~/services/auth.server";
|
||||||
import { getUserId } from "~/services/session.server";
|
import { getUserId } from "~/services/session.server";
|
||||||
import {
|
import {
|
||||||
@ -65,10 +71,14 @@ export async function loader({ request }: LoaderFunctionArgs): Promise<any> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const magicLinkSent = new Cookie(request.headers.get("cookie") ?? "").has(
|
||||||
|
"core:magiclink",
|
||||||
|
);
|
||||||
|
|
||||||
return typedjson(
|
return typedjson(
|
||||||
{
|
{
|
||||||
emailLoginEnabled: true,
|
emailLoginEnabled: true,
|
||||||
magicLinkSent: session.has("core:magiclink"),
|
magicLinkSent,
|
||||||
magicLinkError,
|
magicLinkError,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -93,14 +103,19 @@ export async function action({ request }: ActionFunctionArgs) {
|
|||||||
.parse(payload);
|
.parse(payload);
|
||||||
|
|
||||||
if (action === "send") {
|
if (action === "send") {
|
||||||
return await authenticator.authenticate("email-link", request);
|
const headers = await authenticator
|
||||||
|
.authenticate("email-link", request)
|
||||||
|
.catch((headers) => headers);
|
||||||
|
throw redirect("/login/magic", { headers });
|
||||||
} else {
|
} else {
|
||||||
const session = await getUserSession(request);
|
const myCookie = createCookie("core:magiclink");
|
||||||
session.unset("core:magiclink");
|
|
||||||
|
|
||||||
return redirect("/magic", {
|
return redirect("/login/magic", {
|
||||||
headers: {
|
headers: {
|
||||||
"Set-Cookie": await commitSession(session),
|
"Set-Cookie": await myCookie.serialize("", {
|
||||||
|
maxAge: 0,
|
||||||
|
path: "/",
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -130,80 +145,81 @@ export default function LoginMagicLinkPage() {
|
|||||||
<Form method="post">
|
<Form method="post">
|
||||||
<div className="flex flex-col items-center justify-center">
|
<div className="flex flex-col items-center justify-center">
|
||||||
{data.magicLinkSent ? (
|
{data.magicLinkSent ? (
|
||||||
<>
|
<Card className="min-w-[400px] rounded-md p-3">
|
||||||
<Header1 className="pb-6 text-center text-xl leading-7 font-normal md:text-xl lg:text-2xl">
|
<CardHeader className="flex flex-col items-start">
|
||||||
We've sent you a magic link!
|
<CardTitle className="mb-0 text-lg">
|
||||||
</Header1>
|
{" "}
|
||||||
<Fieldset className="flex w-full flex-col items-center gap-y-2">
|
We've sent you a magic link!
|
||||||
<Inbox className="text-primary mb-4 h-12 w-12" />
|
</CardTitle>
|
||||||
<Paragraph className="mb-6 text-center">
|
<CardDescription>
|
||||||
We sent you an email which contains a magic link that will log
|
We sent you an email which contains a magic link that will log
|
||||||
you in to your account.
|
you in to your account.
|
||||||
</Paragraph>
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
|
||||||
|
<Fieldset className="flex w-full flex-col items-center gap-y-2 px-2">
|
||||||
<FormButtons
|
<FormButtons
|
||||||
cancelButton={
|
cancelButton={
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
name="action"
|
name="action"
|
||||||
value="reset"
|
value="reset"
|
||||||
variant="link"
|
variant="secondary"
|
||||||
data-action="re-enter email"
|
data-action="re-enter email"
|
||||||
>
|
>
|
||||||
Re-enter email
|
Re-enter email
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
confirmButton={
|
confirmButton={<></>}
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
data-action="log in using another option"
|
|
||||||
>
|
|
||||||
Log in using another option
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Fieldset>
|
</Fieldset>
|
||||||
</>
|
</Card>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<Card className="min-w-[400px] rounded-md p-3">
|
||||||
<Header1 className="pb-4 font-semibold sm:text-2xl md:text-3xl lg:text-4xl">
|
<CardHeader className="flex flex-col items-start">
|
||||||
Welcome
|
<CardTitle className="mb-0 text-lg">Welcome</CardTitle>
|
||||||
</Header1>
|
<CardDescription>
|
||||||
<Paragraph variant="base" className="mb-6 text-center">
|
Create an account or login using email
|
||||||
Create an account or login using email
|
</CardDescription>
|
||||||
</Paragraph>
|
</CardHeader>
|
||||||
<Fieldset className="flex w-full flex-col items-center gap-y-2">
|
<CardContent className="pt-2">
|
||||||
<Input
|
<Fieldset className="flex w-full flex-col items-center gap-y-2">
|
||||||
type="email"
|
<Input
|
||||||
name="email"
|
type="email"
|
||||||
spellCheck={false}
|
name="email"
|
||||||
placeholder="Email Address"
|
className="h-9"
|
||||||
required
|
spellCheck={false}
|
||||||
autoFocus
|
placeholder="Email Address"
|
||||||
/>
|
required
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
name="action"
|
name="action"
|
||||||
value="send"
|
value="send"
|
||||||
type="submit"
|
type="submit"
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
size="lg"
|
size="lg"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
data-action="send a magic link"
|
data-action="send a magic link"
|
||||||
>
|
>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Loader className="mr-2 size-5" color="white" />
|
<Loader className="mr-2 size-5" color="white" />
|
||||||
) : (
|
) : (
|
||||||
<Mail className="text-text-bright mr-2 size-5" />
|
<Mail className="text-text-bright mr-2 size-5" />
|
||||||
)}
|
)}
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<span className="text-text-bright">Sending…</span>
|
<span className="text-text-bright">Sending…</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-text-bright">Send a magic link</span>
|
<span className="text-text-bright">
|
||||||
)}
|
Send a magic link
|
||||||
</Button>
|
</span>
|
||||||
{data.magicLinkError && <>{data.magicLinkError}</>}
|
)}
|
||||||
</Fieldset>
|
</Button>
|
||||||
</>
|
{data.magicLinkError && <>{data.magicLinkError}</>}
|
||||||
|
</Fieldset>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@ -5,9 +5,11 @@ import { json } from "@remix-run/node";
|
|||||||
|
|
||||||
export const SearchBodyRequest = z.object({
|
export const SearchBodyRequest = z.object({
|
||||||
query: z.string(),
|
query: z.string(),
|
||||||
spaceId: z.string().optional(),
|
|
||||||
startTime: z.string().optional(),
|
startTime: z.string().optional(),
|
||||||
endTime: z.string().optional(),
|
endTime: z.string().optional(),
|
||||||
|
|
||||||
|
// These are not supported yet, but need to support these
|
||||||
|
spaceId: z.string().optional(),
|
||||||
limit: z.number().optional(),
|
limit: z.number().optional(),
|
||||||
maxBfsDepth: z.number().optional(),
|
maxBfsDepth: z.number().optional(),
|
||||||
includeInvalidated: z.boolean().optional(),
|
includeInvalidated: z.boolean().optional(),
|
||||||
|
|||||||
@ -13,7 +13,9 @@ const authenticator = new Authenticator<AuthUser>();
|
|||||||
|
|
||||||
const isGoogleAuthSupported =
|
const isGoogleAuthSupported =
|
||||||
typeof env.AUTH_GOOGLE_CLIENT_ID === "string" &&
|
typeof env.AUTH_GOOGLE_CLIENT_ID === "string" &&
|
||||||
typeof env.AUTH_GOOGLE_CLIENT_SECRET === "string";
|
env.AUTH_GOOGLE_CLIENT_ID.length > 0 &&
|
||||||
|
typeof env.AUTH_GOOGLE_CLIENT_SECRET === "string" &&
|
||||||
|
env.AUTH_GOOGLE_CLIENT_SECRET.length > 0;
|
||||||
|
|
||||||
if (env.AUTH_GOOGLE_CLIENT_ID && env.AUTH_GOOGLE_CLIENT_SECRET) {
|
if (env.AUTH_GOOGLE_CLIENT_ID && env.AUTH_GOOGLE_CLIENT_SECRET) {
|
||||||
addGoogleStrategy(
|
addGoogleStrategy(
|
||||||
|
|||||||
@ -58,11 +58,6 @@ function buildTransportOptions(): MailTransportOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function sendMagicLinkEmail(options: any): Promise<void> {
|
export async function sendMagicLinkEmail(options: any): Promise<void> {
|
||||||
// Auto redirect when in development mode
|
|
||||||
if (env.NODE_ENV === "development") {
|
|
||||||
throw redirect(options.magicLink);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug("Sending magic link email", {
|
logger.debug("Sending magic link email", {
|
||||||
emailAddress: options.emailAddress,
|
emailAddress: options.emailAddress,
|
||||||
});
|
});
|
||||||
@ -77,6 +72,7 @@ export async function sendMagicLinkEmail(options: any): Promise<void> {
|
|||||||
logger.error("Error sending magic link email", {
|
logger.error("Error sending magic link email", {
|
||||||
error: JSON.stringify(error),
|
error: JSON.stringify(error),
|
||||||
});
|
});
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,9 @@ const emailStrategy = new EmailLinkStrategy(
|
|||||||
sendEmail: sendMagicLinkEmail,
|
sendEmail: sendMagicLinkEmail,
|
||||||
secret,
|
secret,
|
||||||
magicEndpoint: `${APP_ORIGIN}/magic`,
|
magicEndpoint: `${APP_ORIGIN}/magic`,
|
||||||
|
cookie: {
|
||||||
|
name: "core:magiclink",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
async ({ email }: { email: string }) => {
|
async ({ email }: { email: string }) => {
|
||||||
logger.info("Magic link user authenticated", { email });
|
logger.info("Magic link user authenticated", { email });
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
"@core/database": "workspace:*",
|
"@core/database": "workspace:*",
|
||||||
"@core/types": "workspace:*",
|
"@core/types": "workspace:*",
|
||||||
"@opentelemetry/api": "1.9.0",
|
"@opentelemetry/api": "1.9.0",
|
||||||
|
"@mjackson/headers": "0.11.1",
|
||||||
"@radix-ui/react-accordion": "^1.1.2",
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
"@radix-ui/react-alert-dialog": "^1.0.5",
|
"@radix-ui/react-alert-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-avatar": "^1.0.4",
|
"@radix-ui/react-avatar": "^1.0.4",
|
||||||
|
|||||||
@ -1,58 +1,58 @@
|
|||||||
version: "3.8"
|
version: "3.8"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
core:
|
# core:
|
||||||
container_name: core-app
|
# container_name: core-app
|
||||||
image: redplanethq/core:${VERSION}
|
# image: redplanethq/core:${VERSION}
|
||||||
environment:
|
# environment:
|
||||||
- NODE_ENV=${NODE_ENV}
|
# - NODE_ENV=${NODE_ENV}
|
||||||
- DATABASE_URL=${DATABASE_URL}
|
# - DATABASE_URL=${DATABASE_URL}
|
||||||
- DIRECT_URL=${DIRECT_URL}
|
# - DIRECT_URL=${DIRECT_URL}
|
||||||
- SESSION_SECRET=${SESSION_SECRET}
|
# - SESSION_SECRET=${SESSION_SECRET}
|
||||||
- ENCRYPTION_KEY=${ENCRYPTION_KEY}
|
# - ENCRYPTION_KEY=${ENCRYPTION_KEY}
|
||||||
- MAGIC_LINK_SECRET=${MAGIC_LINK_SECRET}
|
# - MAGIC_LINK_SECRET=${MAGIC_LINK_SECRET}
|
||||||
- LOGIN_ORIGIN=${LOGIN_ORIGIN}
|
# - LOGIN_ORIGIN=${LOGIN_ORIGIN}
|
||||||
- APP_ORIGIN=${APP_ORIGIN}
|
# - APP_ORIGIN=${APP_ORIGIN}
|
||||||
- REDIS_HOST=${REDIS_HOST}
|
# - REDIS_HOST=${REDIS_HOST}
|
||||||
- REDIS_PORT=${REDIS_PORT}
|
# - REDIS_PORT=${REDIS_PORT}
|
||||||
- REDIS_TLS_DISABLED=${REDIS_TLS_DISABLED}
|
# - REDIS_TLS_DISABLED=${REDIS_TLS_DISABLED}
|
||||||
- NEO4J_URI=${NEO4J_URI}
|
# - NEO4J_URI=${NEO4J_URI}
|
||||||
- NEO4J_USERNAME=${NEO4J_USERNAME}
|
# - NEO4J_USERNAME=${NEO4J_USERNAME}
|
||||||
- NEO4J_PASSWORD=${NEO4J_PASSWORD}
|
# - NEO4J_PASSWORD=${NEO4J_PASSWORD}
|
||||||
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
# - OPENAI_API_KEY=${OPENAI_API_KEY}
|
||||||
- AUTH_GOOGLE_CLIENT_ID=${AUTH_GOOGLE_CLIENT_ID}
|
# - AUTH_GOOGLE_CLIENT_ID=${AUTH_GOOGLE_CLIENT_ID}
|
||||||
- AUTH_GOOGLE_CLIENT_SECRET=${AUTH_GOOGLE_CLIENT_SECRET}
|
# - AUTH_GOOGLE_CLIENT_SECRET=${AUTH_GOOGLE_CLIENT_SECRET}
|
||||||
- ENABLE_EMAIL_LOGIN=${ENABLE_EMAIL_LOGIN}
|
# - ENABLE_EMAIL_LOGIN=${ENABLE_EMAIL_LOGIN}
|
||||||
ports:
|
# ports:
|
||||||
- "3000:3000"
|
# - "3033:3000"
|
||||||
depends_on:
|
# depends_on:
|
||||||
- postgres
|
# - postgres
|
||||||
- redis
|
# - redis
|
||||||
- neo4j
|
# - neo4j
|
||||||
networks:
|
# networks:
|
||||||
- core
|
# - core
|
||||||
|
|
||||||
postgres:
|
# postgres:
|
||||||
container_name: core-postgres
|
# container_name: core-postgres
|
||||||
image: postgres:15
|
# image: postgres:15
|
||||||
environment:
|
# environment:
|
||||||
- POSTGRES_USER=${POSTGRES_USER}
|
# - POSTGRES_USER=${POSTGRES_USER}
|
||||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
# - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||||
- POSTGRES_DB=${POSTGRES_DB}
|
# - POSTGRES_DB=${POSTGRES_DB}
|
||||||
ports:
|
# ports:
|
||||||
- "5432:5432"
|
# - "5432:5432"
|
||||||
volumes:
|
# volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
# - postgres_data:/var/lib/postgresql/data
|
||||||
networks:
|
# networks:
|
||||||
- core
|
# - core
|
||||||
|
|
||||||
redis:
|
# redis:
|
||||||
container_name: core-redis
|
# container_name: core-redis
|
||||||
image: redis:7
|
# image: redis:7
|
||||||
ports:
|
# ports:
|
||||||
- "6379:6379"
|
# - "6379:6379"
|
||||||
networks:
|
# networks:
|
||||||
- core
|
# - core
|
||||||
|
|
||||||
neo4j:
|
neo4j:
|
||||||
container_name: core-neo4j
|
container_name: core-neo4j
|
||||||
|
|||||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@ -48,6 +48,9 @@ importers:
|
|||||||
'@core/types':
|
'@core/types':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/types
|
version: link:../../packages/types
|
||||||
|
'@mjackson/headers':
|
||||||
|
specifier: 0.11.1
|
||||||
|
version: 0.11.1
|
||||||
'@nichtsam/remix-auth-email-link':
|
'@nichtsam/remix-auth-email-link':
|
||||||
specifier: 3.0.0
|
specifier: 3.0.0
|
||||||
version: 3.0.0(remix-auth@4.2.0)
|
version: 3.0.0(remix-auth@4.2.0)
|
||||||
@ -1520,6 +1523,9 @@ packages:
|
|||||||
'@mjackson/headers@0.10.0':
|
'@mjackson/headers@0.10.0':
|
||||||
resolution: {integrity: sha512-U1Eu1gF979k7ZoIBsJyD+T5l9MjtPONsZfoXfktsQHPJD0s7SokBGx+tLKDLsOY+gzVYAWS0yRFDNY8cgbQzWQ==}
|
resolution: {integrity: sha512-U1Eu1gF979k7ZoIBsJyD+T5l9MjtPONsZfoXfktsQHPJD0s7SokBGx+tLKDLsOY+gzVYAWS0yRFDNY8cgbQzWQ==}
|
||||||
|
|
||||||
|
'@mjackson/headers@0.11.1':
|
||||||
|
resolution: {integrity: sha512-uXXhd4rtDdDwkqAuGef1nuafkCa1NlTmEc1Jzc0NL4YiA1yON1NFXuqJ3hOuKvNKQwkiDwdD+JJlKVyz4dunFA==}
|
||||||
|
|
||||||
'@mjackson/headers@0.9.0':
|
'@mjackson/headers@0.9.0':
|
||||||
resolution: {integrity: sha512-1WFCu2iRaqbez9hcYYI611vcH1V25R+fDfOge/CyKc8sdbzniGfy/FRhNd3DgvFF4ZEEX2ayBrvFHLtOpfvadw==}
|
resolution: {integrity: sha512-1WFCu2iRaqbez9hcYYI611vcH1V25R+fDfOge/CyKc8sdbzniGfy/FRhNd3DgvFF4ZEEX2ayBrvFHLtOpfvadw==}
|
||||||
|
|
||||||
@ -9776,6 +9782,8 @@ snapshots:
|
|||||||
|
|
||||||
'@mjackson/headers@0.10.0': {}
|
'@mjackson/headers@0.10.0': {}
|
||||||
|
|
||||||
|
'@mjackson/headers@0.11.1': {}
|
||||||
|
|
||||||
'@mjackson/headers@0.9.0': {}
|
'@mjackson/headers@0.9.0': {}
|
||||||
|
|
||||||
'@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3':
|
'@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3':
|
||||||
|
|||||||
@ -57,6 +57,7 @@
|
|||||||
"NEO4J_USERNAME",
|
"NEO4J_USERNAME",
|
||||||
"NEO4J_PASSWORD",
|
"NEO4J_PASSWORD",
|
||||||
"OPENAI_API_KEY",
|
"OPENAI_API_KEY",
|
||||||
"MAGIC_LINK_SECRET"
|
"MAGIC_LINK_SECRET",
|
||||||
|
"ENABLE_EMAIL_LOGIN"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user