feat: 🎸 api (#2078)

adding metadata to api

# Description

Please include a summary of the changes and the related issue. Please
also include relevant motivation and context.

## Checklist before requesting a review

Please delete options that are not relevant.

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented hard-to-understand areas
- [ ] I have ideally added tests that prove my fix is effective or that
my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged

## Screenshots (if appropriate):
This commit is contained in:
Stan Girard 2024-01-25 15:56:46 -08:00 committed by GitHub
parent 66ffc6b9aa
commit dfdb294c50
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 298 additions and 135 deletions

1
.gitignore vendored
View File

@ -74,3 +74,4 @@ volumes/db/data/
volumes/storage/stub/stub/quivr/*
supabase/migrations/20240103191539_private.sql
supabase/20240103191539_private.sql
paulgraham.py

View File

@ -15,6 +15,11 @@ RUN apt-get clean && apt-get update && apt-get install -y \
git \
poppler-utils \
tesseract-ocr \
autoconf \
automake \
build-essential \
libtool \
python-dev \
build-essential && \
rm -rf /var/lib/apt/lists/* && apt-get clean

View File

@ -13,6 +13,10 @@ RUN apt-get clean && apt-get update && apt-get install -y \
pandoc \
curl \
git \
autoconf \
automake \
libtool \
python-dev \
build-essential && \
rm -rf /var/lib/apt/lists/* && apt-get clean

View File

@ -2,6 +2,8 @@ import json
from typing import Optional
from uuid import UUID
import jq
import requests
from fastapi import HTTPException
from litellm import completion
from llm.knowledge_brain_qa import KnowledgeBrainQA
@ -23,8 +25,18 @@ chat_service = ChatService()
logger = get_logger(__name__)
class UUIDEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, uuid.UUID):
# if the object is uuid, we simply return the value of uuid
return str(obj)
return super().default(obj)
class APIBrainQA(KnowledgeBrainQA, QAInterface):
user_id: UUID
raw: bool = False
jq_instructions: Optional[str] = None
def __init__(
self,
@ -33,6 +45,8 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
chat_id: str,
streaming: bool = False,
prompt_id: Optional[UUID] = None,
raw: bool = False,
jq_instructions: Optional[str] = None,
**kwargs,
):
user_id = kwargs.get("user_id")
@ -48,6 +62,61 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
**kwargs,
)
self.user_id = user_id
self.raw = raw
self.jq_instructions = jq_instructions
def get_api_call_response_as_text(
self, method, api_url, params, search_params, secrets
) -> str:
headers = {}
api_url_with_search_params = api_url
if search_params:
api_url_with_search_params += "?"
for search_param in search_params:
api_url_with_search_params += (
f"{search_param}={search_params[search_param]}&"
)
for secret in secrets:
headers[secret] = secrets[secret]
try:
if method in ["GET", "DELETE"]:
response = requests.request(
method,
url=api_url_with_search_params,
params=params or None,
headers=headers or None,
)
elif method in ["POST", "PUT", "PATCH"]:
response = requests.request(
method,
url=api_url_with_search_params,
json=params or None,
headers=headers or None,
)
else:
raise ValueError(f"Invalid method: {method}")
return response.text
except Exception as e:
logger.error(f"Error calling API: {e}")
return None
def log_steps(self, message: str, type: str):
if "api" not in self.metadata:
self.metadata["api"] = {}
if "steps" not in self.metadata["api"]:
self.metadata["api"]["steps"] = []
self.metadata["api"]["steps"].append(
{
"number": len(self.metadata["api"]["steps"]),
"type": type,
"message": message,
}
)
async def make_completion(
self,
@ -55,14 +124,19 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
functions,
brain_id: UUID,
recursive_count=0,
should_log_steps=False,
):
should_log_steps=True,
) -> str | None:
if recursive_count > 5:
yield "The assistant is having issues and took more than 5 calls to the API. Please try again later or an other instruction."
self.log_steps(
"The assistant is having issues and took more than 5 calls to the API. Please try again later or an other instruction.",
"error",
)
return
if should_log_steps:
yield "🧠<Deciding what to do>🧠"
if "api" not in self.metadata:
self.metadata["api"] = {}
if "raw" not in self.metadata["api"]:
self.metadata["api"]["raw_enabled"] = self.raw
response = completion(
model=self.model,
@ -81,6 +155,7 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
for chunk in response:
finish_reason = chunk.choices[0].finish_reason
if finish_reason == "stop":
self.log_steps("Quivr has finished", "info")
break
if (
"function_call" in chunk.choices[0].delta
@ -98,11 +173,10 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
arguments = json.loads(function_call["arguments"])
except Exception:
yield f"🧠<Issues with {arguments}>🧠"
self.log_steps(f"Issues with {arguments}", "error")
arguments = {}
if should_log_steps:
yield f"🧠<Calling {brain_id} with arguments {arguments}>🧠"
self.log_steps(f"Calling {brain_id} with arguments {arguments}", "info")
try:
api_call_response = call_brain_api(
@ -113,9 +187,8 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
except Exception as e:
logger.info(f"Error while calling API: {e}")
api_call_response = f"Error while calling API: {e}"
function_name = function_call["name"]
yield f"🧠<The function {function_name} was called and gave The following answer:(data from function) {api_call_response} (end of data from function). Don't call this function again unless there was an error or extremely necessary and asked specifically by the user. If an error, display it to the user in raw.>🧠"
self.log_steps("Quivr has called the API", "info")
messages.append(
{
"role": "function",
@ -124,6 +197,14 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
}
)
self.metadata["api"]["raw_response"] = json.loads(api_call_response)
if self.raw:
# Yield the raw response in a format that can then be catched by the generate_stream function
response_to_yield = f"````raw_response: {api_call_response}````"
yield response_to_yield
return
async for value in self.make_completion(
messages=messages,
functions=functions,
@ -198,6 +279,8 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
if self.prompt_to_use
else None,
"brain_name": brain.name if brain else None,
"brain_id": str(self.brain_id),
"metadata": self.metadata,
}
)
else:
@ -212,6 +295,8 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
if self.prompt_to_use
else None,
"brain_name": brain.name if brain else None,
"brain_id": str(self.brain_id),
"metadata": self.metadata,
}
)
response_tokens = []
@ -221,19 +306,33 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
brain_id=self.brain_id,
should_log_steps=should_log_steps,
):
streamed_chat_history.assistant = value
response_tokens.append(value)
yield f"data: {json.dumps(streamed_chat_history.dict())}"
response_tokens = [
token
for token in response_tokens
if not token.startswith("🧠<") and not token.endswith(">🧠")
]
# Look if the value is a raw response
if value.startswith("````raw_response:"):
raw_value_cleaned = value.replace("````raw_response: ", "").replace(
"````", ""
)
logger.info(f"Raw response: {raw_value_cleaned}")
if self.jq_instructions:
json_raw_value_cleaned = json.loads(raw_value_cleaned)
raw_value_cleaned = (
jq.compile(self.jq_instructions)
.input_value(json_raw_value_cleaned)
.first()
)
streamed_chat_history.assistant = raw_value_cleaned
response_tokens.append(raw_value_cleaned)
yield f"data: {json.dumps(streamed_chat_history.dict())}"
else:
streamed_chat_history.assistant = value
response_tokens.append(value)
yield f"data: {json.dumps(streamed_chat_history.dict())}"
if save_answer:
chat_service.update_message_by_id(
message_id=str(streamed_chat_history.message_id),
user_message=question.question,
assistant="".join(response_tokens),
metadata=self.metadata,
)
def make_completion_without_streaming(
@ -275,7 +374,7 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
arguments = {}
if should_log_steps:
print(f"🧠<Calling {brain_id} with arguments {arguments}>🧠")
self.log_steps(f"Calling {brain_id} with arguments {arguments}", "info")
try:
api_call_response = call_brain_api(
@ -317,6 +416,7 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
chat_id: UUID,
question: ChatQuestion,
save_answer: bool = True,
raw: bool = True,
):
if not self.brain_id:
raise HTTPException(
@ -351,6 +451,7 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
functions=[get_api_brain_definition_as_json_schema(brain)],
brain_id=self.brain_id,
should_log_steps=False,
raw=raw,
)
answer = response.content
@ -378,6 +479,8 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
else None,
"brain_name": brain.name if brain else None,
"message_id": new_chat.message_id,
"metadata": self.metadata,
"brain_id": str(self.brain_id),
}
)
return GetChatHistoryOutput(
@ -389,5 +492,7 @@ class APIBrainQA(KnowledgeBrainQA, QAInterface):
"prompt_title": None,
"brain_name": brain.name,
"message_id": None,
"metadata": self.metadata,
"brain_id": str(self.brain_id),
}
)

View File

@ -87,6 +87,8 @@ class CompositeBrainQA(
streaming=self.streaming,
prompt_id=self.prompt_id,
user_id=str(self.user_id),
raw=brain.raw,
jq_instructions=brain.jq_instructions,
).generate_answer
elif brain.brain_type == BrainType.DOC:
return KnowledgeBrainQA(
@ -138,6 +140,7 @@ class CompositeBrainQA(
else None,
"brain_name": brain.name,
"message_id": new_chat.message_id,
"brain_id": str(brain.id),
}
)
return GetChatHistoryOutput(
@ -151,6 +154,7 @@ class CompositeBrainQA(
else None,
"brain_name": brain.name,
"message_id": None,
"brain_id": str(brain.id),
}
)
@ -232,6 +236,7 @@ class CompositeBrainQA(
else None,
"brain_name": brain.name if brain else None,
"message_id": new_chat.message_id if new_chat else None,
"brain_id": str(brain.id) if brain else None,
}
)
@ -359,6 +364,7 @@ class CompositeBrainQA(
if self.prompt_to_use
else None,
"brain_name": brain.name if brain else None,
"brain_id": str(brain.id) if brain else None,
}
)
else:
@ -373,6 +379,7 @@ class CompositeBrainQA(
if self.prompt_to_use
else None,
"brain_name": brain.name if brain else None,
"brain_id": str(brain.id) if brain else None,
}
)

View File

@ -173,6 +173,7 @@ class KnowledgeBrainQA(BaseModel, QAInterface):
else None,
"brain_name": brain.name if brain else None,
"message_id": new_chat.message_id,
"brain_id": str(brain.brain_id) if brain else None,
}
)
@ -187,6 +188,7 @@ class KnowledgeBrainQA(BaseModel, QAInterface):
else None,
"brain_name": None,
"message_id": None,
"brain_id": str(brain.brain_id) if brain else None,
}
)
@ -263,6 +265,7 @@ class KnowledgeBrainQA(BaseModel, QAInterface):
if self.prompt_to_use
else None,
"brain_name": brain.name if brain else None,
"brain_id": str(brain.brain_id) if brain else None,
"metadata": self.metadata,
}
)
@ -278,6 +281,7 @@ class KnowledgeBrainQA(BaseModel, QAInterface):
if self.prompt_to_use
else None,
"brain_name": brain.name if brain else None,
"brain_id": str(brain.brain_id) if brain else None,
"metadata": self.metadata,
}
)

View File

@ -21,13 +21,6 @@ def get_api_call_response_as_text(
headers[secret] = secrets[secret]
try:
logger.info("🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥")
logger.info(f"Calling API: {api_url_with_search_params}")
logger.info(f"Params: {params}")
logger.info(f"Search params: {search_params}")
logger.info(f"Headers: {headers}")
logger.info(f"Method: {method}")
if method in ["GET", "DELETE"]:
response = requests.request(
method,

View File

@ -20,6 +20,8 @@ class CreateApiBrainDefinition(BaseModel, extra=Extra.forbid):
params: Optional[ApiBrainDefinitionSchema] = ApiBrainDefinitionSchema()
search_params: ApiBrainDefinitionSchema = ApiBrainDefinitionSchema()
secrets: Optional[list[ApiBrainDefinitionSecret]] = []
raw: Optional[bool] = False
jq_instructions: Optional[str] = None
class CreateBrainProperties(BaseModel, extra=Extra.forbid):

View File

@ -43,3 +43,5 @@ class ApiBrainDefinitionEntity(BaseModel, extra=Extra.forbid):
params: ApiBrainDefinitionSchema
search_params: ApiBrainDefinitionSchema
secrets: list[ApiBrainDefinitionSecret]
raw: bool = False
jq_instructions: Optional[str] = None

View File

@ -25,6 +25,8 @@ class BrainEntity(BaseModel):
brain_type: BrainType
brain_definition: Optional[ApiBrainDefinitionEntity]
connected_brains_ids: Optional[List[UUID]]
raw: Optional[bool]
jq_instructions: Optional[str]
@property
def id(self) -> UUID:

View File

@ -6,6 +6,7 @@ from llm.knowledge_brain_qa import KnowledgeBrainQA
from logger import get_logger
from models.settings import BrainSettings, get_supabase_client
from modules.brain.entity.brain_entity import BrainType, RoleEnum
from modules.brain.service.api_brain_definition_service import ApiBrainDefinitionService
from modules.brain.service.brain_authorization_service import (
validate_brain_authorization,
)
@ -15,6 +16,7 @@ from modules.chat.service.chat_service import ChatService
from vectorstore.supabase import CustomSupabaseVectorStore
chat_service = ChatService()
api_brain_definition_service = ApiBrainDefinitionService()
logger = get_logger(__name__)
@ -89,6 +91,9 @@ class BrainfulChat(ChatInterface):
follow_up_questions = chat_service.get_follow_up_question(chat_id)
metadata["follow_up_questions"] = follow_up_questions
metadata["model"] = model
metadata["max_tokens"] = max_tokens
metadata["temperature"] = temperature
brain = brain_service.get_brain_by_id(brain_id_to_use)
if (
@ -120,6 +125,9 @@ class BrainfulChat(ChatInterface):
)
if brain.brain_type == BrainType.API:
brain_definition = api_brain_definition_service.get_api_brain_definition(
brain_id_to_use
)
return APIBrainQA(
chat_id=chat_id,
model=model,
@ -130,4 +138,6 @@ class BrainfulChat(ChatInterface):
prompt_id=prompt_id,
user_id=user_id,
metadata=metadata,
raw=brain_definition.raw,
jq_instructions=brain_definition.jq_instructions,
)

View File

@ -12,7 +12,7 @@ class GetChatHistoryOutput(BaseModel):
message_time: Optional[str]
prompt_title: Optional[str] | None
brain_name: Optional[str] | None
brain_id: Optional[UUID] | None
brain_id: Optional[str] | None # string because UUID is not JSON serializable
metadata: Optional[dict] | None
def dict(self, *args, **kwargs):

View File

@ -39,3 +39,5 @@ pytest-celery
pytesseract==0.3.10
async_generator
posthog==3.1.0
jq==1.6.0

View File

@ -47,6 +47,8 @@ export type ApiBrainDefinition = {
search_params: ApiBrainDefinitionSchema;
params: ApiBrainDefinitionSchema;
secrets?: ApiBrainDefinitionSecret[];
raw: boolean;
jq_instructions: string;
};
export type CreateBrainInput = {

View File

@ -1,3 +1,4 @@
/* eslint-disable max-lines */
import { Content, List, Root } from "@radix-ui/react-tabs";
import { Fragment } from "react";
import { useFormContext } from "react-hook-form";
@ -93,6 +94,31 @@ export const ApiRequestDefinition = (): JSX.Element => {
<SecretsDefinition />
</Content>
</div>
{/* // Add a boolean for raw = False or True by default to False */}
<div className="flex gap-2 w-full items-center">
<label htmlFor="raw-output" className="mr-2">
Raw output
</label>
<input
id="raw-output"
type="checkbox"
className="form-checkbox h-5 w-5 text-indigo-600 rounded focus:ring-2 focus:ring-indigo-400 outline-none"
disabled={readOnly}
{...register("brain_definition.raw")}
/>
</div>
<div className="flex gap-2 w-full items-center">
<label htmlFor="jq_instructions" className="mr-2">
Parsing Instructions
</label>
<input
id="jq_instructions"
type="text"
className="mt-1 line-clamp-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm sm:text-sm border-gray-300 rounded-md outline-none"
disabled={readOnly}
{...register("brain_definition.jq_instructions")}
/>
</div>
</Root>
</>
);

View File

@ -22,6 +22,8 @@ export const addBrainDefaultValues: CreateBrainInput = {
required: [],
},
secrets: [],
raw: false,
jq_instructions: "",
},
connected_brains_ids: [],
};

View File

@ -67,7 +67,7 @@
"date-fns": "2.30.0",
"encoding": "0.1.13",
"eslint": "8.46.0",
"eslint-config-next": "13.5.6",
"eslint-config-next": "^14.1.0",
"eslint-plugin-prefer-arrow": "1.2.3",
"framer-motion": "10.15.0",
"front-matter": "4.0.2",
@ -77,15 +77,15 @@
"i18next-http-backend": "2.2.1",
"lodash": "4.17.21",
"marked": "9.0.3",
"next": "13.5.6",
"next": "^14.1.0",
"next-sitemap": "4.2.3",
"nock": "13.3.2",
"postcss": "8.4.32",
"posthog-js": "1.96.1",
"prettier": "2.8.8",
"pretty-bytes": "6.1.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-dropzone": "14.2.3",
"react-ga4": "2.1.0",
"react-hook-form": "7.45.4",

View File

@ -667,62 +667,67 @@
dependencies:
"@lukeed/csprng" "^1.1.0"
"@next/env@13.5.6", "@next/env@^13.4.3":
"@next/env@14.1.0":
version "14.1.0"
resolved "https://registry.yarnpkg.com/@next/env/-/env-14.1.0.tgz#43d92ebb53bc0ae43dcc64fb4d418f8f17d7a341"
integrity sha512-Py8zIo+02ht82brwwhTg36iogzFqGLPXlRGKQw5s+qP/kMNc4MAyDeEwBKDijk6zTIbegEgu8Qy7C1LboslQAw==
"@next/env@^13.4.3":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.5.6.tgz#c1148e2e1aa166614f05161ee8f77ded467062bc"
integrity sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==
"@next/eslint-plugin-next@13.5.6":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-13.5.6.tgz#cf279b94ddc7de49af8e8957f0c3b7349bc489bf"
integrity sha512-ng7pU/DDsxPgT6ZPvuprxrkeew3XaRf4LAT4FabaEO/hAbvVx4P7wqnqdbTdDn1kgTvsI4tpIgT4Awn/m0bGbg==
"@next/eslint-plugin-next@14.1.0":
version "14.1.0"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.1.0.tgz#29b041233fac7417e22eefa4146432d5cd910820"
integrity sha512-x4FavbNEeXx/baD/zC/SdrvkjSby8nBn8KcCREqk6UuwvwoAPZmaV8TFCAuo/cpovBRTIY67mHhe86MQQm/68Q==
dependencies:
glob "7.1.7"
glob "10.3.10"
"@next/swc-darwin-arm64@13.5.6":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.6.tgz#b15d139d8971360fca29be3bdd703c108c9a45fb"
integrity sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==
"@next/swc-darwin-arm64@14.1.0":
version "14.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.1.0.tgz#70a57c87ab1ae5aa963a3ba0f4e59e18f4ecea39"
integrity sha512-nUDn7TOGcIeyQni6lZHfzNoo9S0euXnu0jhsbMOmMJUBfgsnESdjN97kM7cBqQxZa8L/bM9om/S5/1dzCrW6wQ==
"@next/swc-darwin-x64@13.5.6":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.6.tgz#9c72ee31cc356cb65ce6860b658d807ff39f1578"
integrity sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==
"@next/swc-darwin-x64@14.1.0":
version "14.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.1.0.tgz#0863a22feae1540e83c249384b539069fef054e9"
integrity sha512-1jgudN5haWxiAl3O1ljUS2GfupPmcftu2RYJqZiMJmmbBT5M1XDffjUtRUzP4W3cBHsrvkfOFdQ71hAreNQP6g==
"@next/swc-linux-arm64-gnu@13.5.6":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.6.tgz#59f5f66155e85380ffa26ee3d95b687a770cfeab"
integrity sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==
"@next/swc-linux-arm64-gnu@14.1.0":
version "14.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.1.0.tgz#893da533d3fce4aec7116fe772d4f9b95232423c"
integrity sha512-RHo7Tcj+jllXUbK7xk2NyIDod3YcCPDZxj1WLIYxd709BQ7WuRYl3OWUNG+WUfqeQBds6kvZYlc42NJJTNi4tQ==
"@next/swc-linux-arm64-musl@13.5.6":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.6.tgz#f012518228017052736a87d69bae73e587c76ce2"
integrity sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==
"@next/swc-linux-arm64-musl@14.1.0":
version "14.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.1.0.tgz#d81ddcf95916310b8b0e4ad32b637406564244c0"
integrity sha512-v6kP8sHYxjO8RwHmWMJSq7VZP2nYCkRVQ0qolh2l6xroe9QjbgV8siTbduED4u0hlk0+tjS6/Tuy4n5XCp+l6g==
"@next/swc-linux-x64-gnu@13.5.6":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.6.tgz#339b867a7e9e7ee727a700b496b269033d820df4"
integrity sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==
"@next/swc-linux-x64-gnu@14.1.0":
version "14.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.1.0.tgz#18967f100ec19938354332dcb0268393cbacf581"
integrity sha512-zJ2pnoFYB1F4vmEVlb/eSe+VH679zT1VdXlZKX+pE66grOgjmKJHKacf82g/sWE4MQ4Rk2FMBCRnX+l6/TVYzQ==
"@next/swc-linux-x64-musl@13.5.6":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.6.tgz#ae0ae84d058df758675830bcf70ca1846f1028f2"
integrity sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==
"@next/swc-linux-x64-musl@14.1.0":
version "14.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.1.0.tgz#77077cd4ba8dda8f349dc7ceb6230e68ee3293cf"
integrity sha512-rbaIYFt2X9YZBSbH/CwGAjbBG2/MrACCVu2X0+kSykHzHnYH5FjHxwXLkcoJ10cX0aWCEynpu+rP76x0914atg==
"@next/swc-win32-arm64-msvc@13.5.6":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.6.tgz#a5cc0c16920485a929a17495064671374fdbc661"
integrity sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==
"@next/swc-win32-arm64-msvc@14.1.0":
version "14.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.1.0.tgz#5f0b8cf955644104621e6d7cc923cad3a4c5365a"
integrity sha512-o1N5TsYc8f/HpGt39OUQpQ9AKIGApd3QLueu7hXk//2xq5Z9OxmV6sQfNp8C7qYmiOlHYODOGqNNa0e9jvchGQ==
"@next/swc-win32-ia32-msvc@13.5.6":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.6.tgz#6a2409b84a2cbf34bf92fe714896455efb4191e4"
integrity sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==
"@next/swc-win32-ia32-msvc@14.1.0":
version "14.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.1.0.tgz#21f4de1293ac5e5a168a412b139db5d3420a89d0"
integrity sha512-XXIuB1DBRCFwNO6EEzCTMHT5pauwaSj4SWs7CYnME57eaReAKBXCnkUE80p/pAZcewm7hs+vGvNqDPacEXHVkw==
"@next/swc-win32-x64-msvc@13.5.6":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.6.tgz#4a3e2a206251abc729339ba85f60bc0433c2865d"
integrity sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==
"@next/swc-win32-x64-msvc@14.1.0":
version "14.1.0"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.1.0.tgz#e561fb330466d41807123d932b365cf3d33ceba2"
integrity sha512-9WEbVRRAqJ3YFVqEZIxUqkiO8l1nool1LmNxygr5HWF8AcSYsEpneUDhmjUVJEzO2A04+oPtZdombzzPPkTtgg==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
@ -3564,7 +3569,7 @@ camelcase-css@^2.0.1:
resolved "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz"
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001517:
caniuse-lite@^1.0.30001517:
version "1.0.30001519"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz"
integrity sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==
@ -3574,6 +3579,11 @@ caniuse-lite@^1.0.30001538, caniuse-lite@^1.0.30001565:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz#1ccf7dc92d2ee2f92ed3a54e11b7b4a3041acfa0"
integrity sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw==
caniuse-lite@^1.0.30001579:
version "1.0.30001580"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001580.tgz#e3c76bc6fe020d9007647044278954ff8cd17d1e"
integrity sha512-mtj5ur2FFPZcCEpXFy8ADXbDACuNFXg6mxVDqp7tqooX6l3zwm+d8EPoeOSIFRDvHs8qu7/SLFOGniULkcH2iA==
case-anything@^2.1.13:
version "2.1.13"
resolved "https://registry.yarnpkg.com/case-anything/-/case-anything-2.1.13.tgz#0cdc16278cb29a7fcdeb072400da3f342ba329e9"
@ -4491,12 +4501,12 @@ escape-string-regexp@^4.0.0:
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
eslint-config-next@13.5.6:
version "13.5.6"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-13.5.6.tgz#3a5a6222d5cb32256760ad68ab8e976e866a08c8"
integrity sha512-o8pQsUHTo9aHqJ2YiZDym5gQAMRf7O2HndHo/JZeY7TDD+W4hk6Ma8Vw54RHiBeb7OWWO5dPirQB+Is/aVQ7Kg==
eslint-config-next@^14.1.0:
version "14.1.0"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.1.0.tgz#7e309d426b8afacaba3b32fdbb02ba220b6d0a97"
integrity sha512-SBX2ed7DoRFXC6CQSLc/SbLY9Ut6HxNB2wPTcoIWjUMd7aF7O/SIE7111L8FdZ9TXsNV4pulUDnfthpyPtbFUg==
dependencies:
"@next/eslint-plugin-next" "13.5.6"
"@next/eslint-plugin-next" "14.1.0"
"@rushstack/eslint-patch" "^1.3.3"
"@typescript-eslint/parser" "^5.4.2 || ^6.0.0"
eslint-import-resolver-node "^0.3.6"
@ -5091,10 +5101,16 @@ glob-parent@^6.0.2:
dependencies:
is-glob "^4.0.3"
glob-to-regexp@^0.4.1:
version "0.4.1"
resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz"
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
glob@10.3.10, glob@^10.2.2, glob@^10.3.10:
version "10.3.10"
resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b"
integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==
dependencies:
foreground-child "^3.1.0"
jackspeak "^2.3.5"
minimatch "^9.0.1"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
path-scurry "^1.10.1"
glob@7.1.6:
version "7.1.6"
@ -5108,29 +5124,6 @@ glob@7.1.6:
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@7.1.7:
version "7.1.7"
resolved "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz"
integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^3.0.4"
once "^1.3.0"
path-is-absolute "^1.0.0"
glob@^10.2.2, glob@^10.3.10:
version "10.3.10"
resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b"
integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==
dependencies:
foreground-child "^3.1.0"
jackspeak "^2.3.5"
minimatch "^9.0.1"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
path-scurry "^1.10.1"
glob@^7.1.3:
version "7.2.3"
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
@ -5203,7 +5196,7 @@ gopd@^1.0.1:
dependencies:
get-intrinsic "^1.1.3"
graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6:
graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6:
version "4.2.11"
resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
@ -6767,28 +6760,28 @@ next-tick@^1.1.0:
resolved "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz"
integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
next@13.5.6:
version "13.5.6"
resolved "https://registry.yarnpkg.com/next/-/next-13.5.6.tgz#e964b5853272236c37ce0dd2c68302973cf010b1"
integrity sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==
next@^14.1.0:
version "14.1.0"
resolved "https://registry.yarnpkg.com/next/-/next-14.1.0.tgz#b31c0261ff9caa6b4a17c5af019ed77387174b69"
integrity sha512-wlzrsbfeSU48YQBjZhDzOwhWhGsy+uQycR8bHAOt1LY1bn3zZEcDyHQOEoN3aWzQ8LHCAJ1nqrWCc9XF2+O45Q==
dependencies:
"@next/env" "13.5.6"
"@next/env" "14.1.0"
"@swc/helpers" "0.5.2"
busboy "1.6.0"
caniuse-lite "^1.0.30001406"
caniuse-lite "^1.0.30001579"
graceful-fs "^4.2.11"
postcss "8.4.31"
styled-jsx "5.1.1"
watchpack "2.4.0"
optionalDependencies:
"@next/swc-darwin-arm64" "13.5.6"
"@next/swc-darwin-x64" "13.5.6"
"@next/swc-linux-arm64-gnu" "13.5.6"
"@next/swc-linux-arm64-musl" "13.5.6"
"@next/swc-linux-x64-gnu" "13.5.6"
"@next/swc-linux-x64-musl" "13.5.6"
"@next/swc-win32-arm64-msvc" "13.5.6"
"@next/swc-win32-ia32-msvc" "13.5.6"
"@next/swc-win32-x64-msvc" "13.5.6"
"@next/swc-darwin-arm64" "14.1.0"
"@next/swc-darwin-x64" "14.1.0"
"@next/swc-linux-arm64-gnu" "14.1.0"
"@next/swc-linux-arm64-musl" "14.1.0"
"@next/swc-linux-x64-gnu" "14.1.0"
"@next/swc-linux-x64-musl" "14.1.0"
"@next/swc-win32-arm64-msvc" "14.1.0"
"@next/swc-win32-ia32-msvc" "14.1.0"
"@next/swc-win32-x64-msvc" "14.1.0"
nock@13.3.2:
version "13.3.2"
@ -7596,9 +7589,9 @@ rc@^1.2.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
react-dom@18.2.0, react-dom@^18.2.0:
react-dom@^18.2.0:
version "18.2.0"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
dependencies:
loose-envify "^1.1.0"
@ -7735,9 +7728,9 @@ react-use@17.4.0:
ts-easing "^0.2.0"
tslib "^2.1.0"
react@18.2.0, react@^18.2.0:
react@^18.2.0:
version "18.2.0"
resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
dependencies:
loose-envify "^1.1.0"
@ -9505,14 +9498,6 @@ w3c-xmlserializer@^4.0.0:
dependencies:
xml-name-validator "^4.0.0"
watchpack@2.4.0:
version "2.4.0"
resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz"
integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
dependencies:
glob-to-regexp "^0.4.1"
graceful-fs "^4.1.2"
web-namespaces@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.1.tgz#1010ff7c650eccb2592cebeeaf9a1b253fd40692"

View File

@ -0,0 +1,11 @@
alter table "public"."api_brain_definition" add column "jq_instructions" text not null default ''::text;
alter table "public"."api_brain_definition" add column "raw" boolean not null default false;
alter table "public"."api_brain_definition" alter column "brain_id" set not null;
CREATE UNIQUE INDEX api_brain_definition_pkey ON public.api_brain_definition USING btree (brain_id);
alter table "public"."api_brain_definition" add constraint "api_brain_definition_pkey" PRIMARY KEY using index "api_brain_definition_pkey";