Skip to content
Merged

Dev #33

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
b3ed15b
Merge pull request #11 from MicroClub-USTHB/main
YounesBensafia Feb 26, 2026
9ca74db
refactor: migrate dependency management from requirements.txt to pypr…
YounesBensafia Feb 26, 2026
2ea24d7
feat: add dynamic system prompt generation with core rules and org in…
nisbenz Feb 26, 2026
7358151
Merge pull request #12 from MicroClub-USTHB/nisbenz/10-core-organizat…
YounesBensafia Feb 28, 2026
886cffe
docs: update README to enhance project overview, goals, core concepts…
YounesBensafia Mar 7, 2026
17da92e
fix: correct spelling of 'mAIcro' in README Dockerfile, docker-compos…
YounesBensafia Mar 7, 2026
9f541d1
Refactor code structure for improved readability and maintainability
YounesBensafia Mar 7, 2026
f78fb3b
Refactor code structure for improved readability and maintainability
YounesBensafia Mar 7, 2026
867f8e6
chore: remove unused files and configurations to streamline the proje…
YounesBensafia Mar 7, 2026
81aacff
feat: Initialize project structure, integrate Google Gemini embedding…
YounesBensafia Mar 7, 2026
8f23b52
refactor: replace `RetrievalQA` with a LangChain Expression Language …
YounesBensafia Mar 7, 2026
ce428b4
feat: Update default AI model name from gemini-1.5-flash to gemini-2.…
YounesBensafia Mar 7, 2026
cd34045
feat: Update default AI model to gemini-2.0-flash-lite.
YounesBensafia Mar 7, 2026
e2fa889
feat: Enhance error handling in ask.py for LLM requests
YounesBensafia Mar 7, 2026
c7a8240
feat: Integrate Anthropic LLM, update dependencies, and clarify inges…
YounesBensafia Mar 7, 2026
5159f8e
chore: Add `__init__.py` files to `app` and `app/core` directories.
YounesBensafia Mar 7, 2026
3e26e97
feat: Add FastAPI, Uvicorn, and their sub-dependencies.
YounesBensafia Mar 7, 2026
d2b32d6
feat: Add Discord bot token and channel ID configuration with a parsi…
YounesBensafia Mar 7, 2026
944ad5f
feat: Initialize FastAPI application and add API routes for health, a…
YounesBensafia Mar 7, 2026
350ccac
Update microclub knowledge base data in local Qdrant storage.
YounesBensafia Mar 7, 2026
4eb39dc
feat: add Groq as a new LLM provider with corresponding configuration…
YounesBensafia Mar 7, 2026
35af3c1
fix: update model name and remove unused Discord configuration from s…
YounesBensafia Mar 7, 2026
4479790
feat: add Discord bot token and channel ID configuration with parsing…
YounesBensafia Mar 7, 2026
485d0d8
feat: enhance prompt templates for retrieval-augmented generation and…
YounesBensafia Mar 7, 2026
aac3f68
feat: question-answering service implementation
YounesBensafia Mar 7, 2026
668e65d
refactor: remove unused request/response models and streamline import…
YounesBensafia Mar 7, 2026
14e1a28
fix: improve error handling for configuration issues and enhance fall…
YounesBensafia Mar 7, 2026
3dc309c
fix: add missing import for lru_cache and clean up whitespace in vect…
YounesBensafia Mar 7, 2026
01a211c
fix: enhance error handling for vector store initialization and impro…
YounesBensafia Mar 7, 2026
3d98284
feat: add example environment configuration file
YounesBensafia Mar 8, 2026
a64419e
fix: update get_llm function to accept provider override and enhance …
YounesBensafia Mar 8, 2026
40a8044
fix: improve timeout handling in _invoke_with_timeout and ensure exec…
YounesBensafia Mar 8, 2026
d766f84
fix: enhance error handling in Discord ingestion and improve response…
YounesBensafia Mar 8, 2026
c6b7fe7
feat: add centralized FastAPI exception handlers for improved error m…
YounesBensafia Mar 8, 2026
5ab880c
fix: configure logging and register exception handlers in main applic…
YounesBensafia Mar 8, 2026
3745398
fix: remove unnecessary exception handling in ask and ingest endpoint…
YounesBensafia Mar 8, 2026
efe2d8f
Refactor code structure for improved readability and maintainability
YounesBensafia Mar 8, 2026
460fba3
fix: remove discord_fetcher.py for cleaner code
YounesBensafia Mar 8, 2026
f6fe2d3
Add entrypoints for asking questions and ingesting data
YounesBensafia Mar 8, 2026
af62fe6
fix: update ingestion logic to use vector store directly for document…
YounesBensafia Mar 8, 2026
9443982
fix: streamline LLM provider checks and remove Groq fallback logic fo…
YounesBensafia Mar 8, 2026
7a5d7fe
feat: migrate mAIcro to Gemini-only, harden ingestion, and prep OSS p…
YounesBensafia Mar 8, 2026
753e11a
fix: add dependency group for development and implement tests for LLM…
YounesBensafia Mar 8, 2026
fcf5c4c
fix: add iniconfig, pluggy, pygments, pytest, and tomli packages with…
YounesBensafia Mar 8, 2026
919d7a7
fix: refactor settings configuration to use SettingsConfigDict for im…
YounesBensafia Mar 8, 2026
76852cc
fix: implement API fallback for ingestion when local Qdrant is locked
YounesBensafia Mar 8, 2026
175be7c
fix: handle user cancellation in ask_main and _invoke_with_timeout
YounesBensafia Mar 8, 2026
095e27d
fix: update README and CLI commands for correct app entrypoint; add p…
YounesBensafia Mar 8, 2026
756c5b8
fix: enhance ingestion to support Discord with message limit; update …
YounesBensafia Mar 8, 2026
85dd48f
feat: add initial implementation of content generation using Google G…
YounesBensafia Mar 8, 2026
6ffa892
feat: Implement mAIcro API with Discord ingestion and question-answer…
YounesBensafia Mar 8, 2026
727e3ca
fix: update README for API usage and remove script references from py…
YounesBensafia Mar 8, 2026
3e3f3c4
fix: ensure collection creation in vector store during document inges…
YounesBensafia Mar 8, 2026
6a8f023
fix: refactor Qdrant client initialization and ensure collection crea…
YounesBensafia Mar 8, 2026
e4db552
fix: update GOOGLE_MODEL_NAME to use the latest version "gemini-2.5-f…
YounesBensafia Mar 9, 2026
8f51b03
feat: add latest Discord message retrieval and related tests
YounesBensafia Mar 9, 2026
7dc5d54
feat: enhance question normalization and retrieval logic in QA service
YounesBensafia Mar 9, 2026
9e4962e
feat: add tests for question normalization and retrieval with rewrites
YounesBensafia Mar 9, 2026
6932672
feat: enhance question processing by adding temporal context augmenta…
YounesBensafia Mar 9, 2026
1c8ae6b
feat: add support for today's updates query in QA service with corres…
YounesBensafia Mar 9, 2026
dd55b05
feat: enhance today updates query pattern and add corresponding test
YounesBensafia Mar 9, 2026
ab01592
feat: add tests for today updates query handling and fallback logic
YounesBensafia Mar 9, 2026
4a7f748
feat: add ingestion tests for Discord message handling and collection…
YounesBensafia Mar 10, 2026
7065de8
feat: refactor tests to use async client for improved performance
YounesBensafia Mar 10, 2026
3f143e0
feat: remove test file for Google GenAI client
YounesBensafia Mar 10, 2026
dce069f
Prepare for open source
YounesBensafia Mar 10, 2026
24489ac
feat: enhance configuration and error handling for Qdrant integration
YounesBensafia Mar 10, 2026
31cb65f
feat: improve error handling for ingestion and Qdrant client initiali…
YounesBensafia Mar 10, 2026
61b996a
feat: enhance error handling and bootstrap collection for Qdrant inte…
YounesBensafia Mar 11, 2026
4aac7b9
feat: add error handling for missing Qdrant collection in ask_question
YounesBensafia Mar 11, 2026
d882d14
feat: add tests for handling missing Qdrant collection in ingestion a…
YounesBensafia Mar 11, 2026
2b3e21f
Merge pull request #20 from MicroClub-USTHB/younes/enhance
YounesBensafia Mar 12, 2026
64d72f8
feat: remove JSON ingestion support and update related documentation
Tyjfre-j Mar 12, 2026
9d7f18b
Merge pull request #21 from MicroClub-USTHB/Depresso/fix
YounesBensafia Mar 12, 2026
d13fe78
feat: update contributing guidelines and README for improved setup in…
YounesBensafia Mar 13, 2026
283b179
feat: Introduce persistent state tracking for Discord message ingesti…
nisbenz Mar 14, 2026
ac276e2
Fix: fix bootstrap and catch-up ingestion fetch behaviourBootstrap (n…
nisbenz Mar 14, 2026
a57dcf3
feat: Remove `limit_per_channel` from `ingest_from_discord` and imple…
nisbenz Mar 14, 2026
6ee776b
feat: Add Discord listening functionality with a new module, main ent…
nisbenz Mar 15, 2026
9f4f67b
feat: Implement Discord message ingestion with a real-time listener a…
nisbenz Mar 15, 2026
d3c5463
fix: run ask_question in thread executor to unblock event loop
nisbenz Mar 15, 2026
154aadf
feat: add message delete/edit handlers to Discord listener
nisbenz Mar 15, 2026
41dcdce
refactor(audit): use cursor-based auditing instead of full window scan
nisbenz Mar 15, 2026
521524e
Merge pull request #23 from MicroClub-USTHB/nisbenz/discord-fetch
YounesBensafia Mar 16, 2026
61ba85b
chore: remove unused agent_engine and embeddings modules
YounesBensafia Mar 16, 2026
2dfb87c
refactor: drop unused DISCORD_API constant and dead debug line in aud…
YounesBensafia Mar 16, 2026
593052e
feat(ingestion): handle missing Qdrant collection exceptions and impr…
YounesBensafia Mar 17, 2026
0428219
feat: Prioritize Qdrant setup in README and `.env.example` configurat…
YounesBensafia Mar 17, 2026
564aa72
feat: update quickstart guide with Discord integration setup and API …
YounesBensafia Mar 17, 2026
a6377bb
feat: Implement Qdrant payload indexing for cloud compatibility and r…
YounesBensafia Mar 17, 2026
32c267c
docs: Add detailed troubleshooting and Discord bot setup guides to th…
YounesBensafia Mar 17, 2026
317db14
feat: Enforce Qdrant Cloud integration by requiring API key and remov…
YounesBensafia Mar 17, 2026
c5d460e
feat: Migrate ingestion state management from local files to Qdrant a…
YounesBensafia Mar 17, 2026
1f7f974
docs: update README with new server run instructions, including Docke…
YounesBensafia Mar 17, 2026
f57934c
refactor: Remove standalone `ingest.py`, `main.py`, and `ask.py` scri…
YounesBensafia Mar 17, 2026
22dcd94
test: add conftest.py with a pytest fixture to mock environment varia…
YounesBensafia Mar 17, 2026
7e20b43
feat: Add architecture diagrams and update quickstart
YounesBensafia Mar 17, 2026
127d562
Update section headings in README
YounesBensafia Mar 17, 2026
f1ddd96
Update image in README.md
YounesBensafia Mar 17, 2026
5ba49bc
feat: Rename Google API key to Gemini API key and add a dedicated hea…
YounesBensafia Mar 18, 2026
b30768d
chore: Remove policy document and the command-line interface for aski…
YounesBensafia Mar 18, 2026
745d207
docs: Update README to specify environment variable names for credent…
YounesBensafia Mar 18, 2026
a70ae8c
refactor: rename `GOOGLE_API_KEY` to `GEMINI_API_KEY` in LLM provider…
YounesBensafia Mar 18, 2026
5f57270
Merge pull request #24 from MicroClub-USTHB/younes/finalizing
YounesBensafia Mar 18, 2026
ba557ff
feat: enhance .env.example with secondary LLM provider configuration …
Tyjfre-j Mar 18, 2026
d84c17c
feat(qdrant): add full-text payload index on page_content for hybrid …
nisbenz Mar 18, 2026
562310a
test: add FakeClient with collection_exists mock to ingestion bootstr…
nisbenz Mar 18, 2026
e705e48
docs: update LLM env template
Tyjfre-j Mar 18, 2026
0131c1f
chore(config): restore Google model defaults
Tyjfre-j Mar 18, 2026
38489f7
feat(llm): add Gemini fallback routing
Tyjfre-j Mar 18, 2026
4795fcb
chore(qa): make LLM result handling provider-agnostic
Tyjfre-j Mar 18, 2026
c0a3914
feat: add hybrid search configuration and integration
nisbenz Mar 18, 2026
dc3db16
refactor(qa): use hybrid search retriever
nisbenz Mar 18, 2026
903eb91
fix(hybrid_search): search by message ID using keyword index
nisbenz Mar 18, 2026
0e192aa
refactor hybrid search
nisbenz Mar 18, 2026
92a5bdb
Restrict CI triggers to dev and main branches
Adel2411 Mar 18, 2026
afdac82
Fixed dockerfile and docker-compose files
Adel2411 Mar 18, 2026
206229e
Switched prefix definition to main.py and removed duplicate health route
Adel2411 Mar 18, 2026
91b81e3
Removed all inline comments in env files and non-ASCII characters
Adel2411 Mar 18, 2026
cf20458
Created development docker-compose
Adel2411 Mar 18, 2026
94ad8a0
Merge pull request #31 from MicroClub-USTHB/nisbenz/27-hybrid-search-…
YounesBensafia Mar 18, 2026
cc8aa6d
Merge pull request #30 from MicroClub-USTHB/Depresso/llm-resiliency-a…
YounesBensafia Mar 18, 2026
b3f52d9
Remove introductory image from README
YounesBensafia Mar 18, 2026
d18aedf
Refactor (services/qa_service.py) to use Qdrant's scroll or search AP…
maya-ots Mar 18, 2026
6d59fe1
Change logo image in README.md
YounesBensafia Mar 18, 2026
2aa4b3b
Update _retrieve_with_rewrites in services/qa_service.py to handle la…
maya-ots Mar 18, 2026
8ae013e
fix: correct errors
maya-ots Mar 18, 2026
04c5033
test: Reorder test data points in `test_qa_service.py`.
YounesBensafia Mar 18, 2026
f19319a
Merge pull request #32 from MicroClub-USTHB/Maya/26-scalable-knowledg…
YounesBensafia Mar 18, 2026
c455c79
refactor: remove secondary LLM provider configuration from .env.example
YounesBensafia Mar 18, 2026
d8a7bc3
feat: add MIT License file.
YounesBensafia Mar 18, 2026
81d9a94
feat: Implement core Q&A service with RAG, Discord integration, and r…
YounesBensafia Mar 18, 2026
04089d2
docs: enhance clarity on setup, features, and use cases
YounesBensafia Mar 18, 2026
32005e8
docs: update README with additional Discord Channels IDS and clarify …
YounesBensafia Mar 18, 2026
a1572e5
fixed entire README without ghcr specification and fixed docker compo…
Adel2411 Mar 18, 2026
f6561d5
Finalized README.md file and created new release workflow
Adel2411 Mar 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
__pycache__/
*.py[cod]
*$py.class
.venv/
.env
local_qdrant/
var/
data/
.git/
.github/
.pytest_cache/
tests/
42 changes: 34 additions & 8 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@
# mAIcro Configuration
ORG_NAME="MicroClub-USTHB"
ORG_DESCRIPTION="The first Algerian Scientific Club, founded in 1985."
# ─────────────────────────────────────────────────
# mAIcro — Environment Configuration
# Copy this file to .env and fill in your values.
# ─────────────────────────────────────────────────

# AI Providers
GEMINI_KEY="your-key-here"
MODEL_NAME="xxx"
# ── LLM Provider ────────────────────────────────
LLM_PROVIDER=google
GEMINI_API_KEY=

# Database
DATABASE_URL="postgresql://user:pass@localhost:5432/maicro"

# ── Discord ─────────────────────────────────────
# Create a bot at https://discord.com/developers/applications
# Enable MESSAGE CONTENT intent, then invite the bot to your server
# with "Read Message History" + "View Channels" permissions.

# Discord Bot Token (Bot -> Token -> Copy)
DISCORD_BOT_TOKEN=

# Comma-separated channel IDs to ingest, e.g. 123456789,987654321
DISCORD_CHANNEL_IDS=

# ── Qdrant (Vector Database) ────────────────────
# Sign up for the free 1 GB tier at https://cloud.qdrant.io
# Create a cluster -> copy the URL and API key below.

# Qdrant URL (e.g. https://abc123-xyz.us-east4-0.gcp.cloud.qdrant.io:6333)
QDRANT_URL=

# Qdrant API Key (Cluster -> API Keys -> Create)
QDRANT_API_KEY=

# ── Organization (optional) ─────────────────────
# Customize the AI personality for your org.
# ORG_NAME=MyOrganization
# ORG_DESCRIPTION=A brief description of your organization
# COLLECTION_NAME=my_org_knowledge
36 changes: 36 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: CI

on:
push:
branches:
- dev
pull_request:
branches:
- dev
- main

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Set up uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"

- name: Install dependencies
run: uv sync --dev

- name: Run tests
run: uv run pytest
91 changes: 91 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Release

on:
push:
branches: [main]
tags: ["v*"]

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/maicro

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=sha-,format=short
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable={{is_default_branch}}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push
id: build
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
provenance: true
sbom: true

- name: Generate attestation
uses: actions/attest-build-provenance@v2
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
push-to-registry: true

- name: Make GHCR package public
if: always()
env:
GITHUB_API_URL: https://api.github.com
OWNER: ${{ github.repository_owner }}
PACKAGE: maicro
TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
echo "Checking owner type for $OWNER"
owner_type=$(curl -sS -H "Authorization: Bearer $TOKEN" "$GITHUB_API_URL/users/$OWNER" | python -c "import sys, json; print(json.load(sys.stdin).get('type',''))")
echo "Owner type: $owner_type"
if [ "$owner_type" = "Organization" ]; then
url="$GITHUB_API_URL/orgs/$OWNER/packages/container/$PACKAGE/visibility"
else
url="$GITHUB_API_URL/user/packages/container/$PACKAGE/visibility"
fi
echo "Making package public via $url"
resp=$(curl -sS -o /dev/stderr -w "%{http_code}" -X PUT -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $TOKEN" "$url" -d '{"visibility":"public"}')
if [ "$resp" -ge 200 ] && [ "$resp" -lt 300 ]; then
echo "Package visibility set to public"
else
echo "Failed to set package visibility (status $resp). You may need to make the package public manually in the GitHub UI or grant the workflow token additional permissions." >&2
exit 0
fi
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ lib64/
parts/
sdist/
var/
local_qdrant/
wheels/
share/python-wheels/
*.egg-info/
Expand Down Expand Up @@ -205,3 +206,6 @@ cython_debug/
marimo/_static/
marimo/_lsp/
__marimo__/

# Qdrant
qdrant_storage/
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.13
49 changes: 49 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Contributing

Thanks for your interest in contributing to **mAIcro**.

## Ways to help

- Report bugs (include steps to reproduce and expected vs actual behavior).
- Suggest features (include the problem you’re trying to solve and constraints).
- Improve docs (typos, examples, setup clarity).
- Send PRs (small, focused changes are easiest to review).

If you’ve found a security issue, please follow `SECURITY.md` instead of opening a public issue.

Start the local dev service:

```bash
uv sync --dev
cp .env.example .env
# Edit .env and set at least:
# LLM_PROVIDER=google
# GEMINI_API_KEY=...
# QDRANT_URL=http://localhost:6333
```

## Common commands

Run tests:

```bash
uv run pytest
```

Start the API locally:

```bash
uv run uvicorn main:app --reload --host 0.0.0.0 --port 8000
```

## Pull requests

- Keep PRs focused and small when possible.
- Include tests for behavior changes and bug fixes.
- Update `README.md` / docs for user-facing changes.
- Don’t commit secrets (keep `.env` local; update `.env.example` if you add a new setting).
- Don’t commit local state directories (for example `var/` or `local_qdrant/`).

## Reporting issues

Use GitHub Issues for bugs and feature requests.
33 changes: 33 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
FROM python:3.12-slim AS builder

RUN pip install uv

ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy

WORKDIR /app

COPY pyproject.toml uv.lock README.md ./

RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-project --no-dev

COPY src ./src

RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen

FROM python:3.12-slim

WORKDIR /app

COPY --from=builder /app/.venv /app/.venv

ENV PATH="/app/.venv/bin:$PATH"
ENV PYTHONPATH="/app/src"

COPY src ./src

EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Micro Club

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Loading
Loading