Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
9ab1432
small refactor clis
BrunoV21 Jul 24, 2025
4c022c5
updated gitignore
BrunoV21 Jul 24, 2025
7c71975
added requirements-agents-ui dependency
BrunoV21 Jul 24, 2025
ac0f1de
added ui skeleton with chainlit
BrunoV21 Jul 24, 2025
447c459
added second pass in _parse_update_file to ensure context matching ev…
BrunoV21 Jul 26, 2025
20cf070
refactored agent-tide-ui
BrunoV21 Jul 26, 2025
ad6d323
added agent-tide-ui entry point
BrunoV21 Jul 26, 2025
3b9e61b
updated README to include cli references
BrunoV21 Jul 26, 2025
bf8e436
improved newline replcament logic
BrunoV21 Jul 27, 2025
ccb38b1
added tests for newline_replacments
BrunoV21 Jul 27, 2025
e4fba6f
added shell wrapping for diffs
BrunoV21 Jul 27, 2025
5c5811c
warpped diffs in steps
BrunoV21 Jul 27, 2025
04525a3
updated ui to support multiple diffs
BrunoV21 Jul 27, 2025
4c04fa8
fixed bug in setup.py
BrunoV21 Jul 27, 2025
d9eb254
added themes, icons, and logos
BrunoV21 Jul 27, 2025
ce9a750
added chainlit.md
BrunoV21 Jul 27, 2025
3ba5992
refactored chainlit ui
BrunoV21 Jul 29, 2025
511a4d2
skipped ruff linting
BrunoV21 Jul 29, 2025
cb4cd1f
updated .gitginore
BrunoV21 Jul 29, 2025
1487c09
added args to serve ui
BrunoV21 Jul 29, 2025
eca9bb3
Add CLI args --project-path and --config-path to agent-tide-ui
BrunoV21 Jul 29, 2025
32efcff
updated chainlit version
BrunoV21 Jul 29, 2025
3b135ca
updated pyproject.toml and setup.py
BrunoV21 Jul 29, 2025
0407495
typo fix
BrunoV21 Jul 29, 2025
8271339
added chainlit directories
BrunoV21 Jul 29, 2025
8accfb8
added local sqlite chainlit compatible datalayer
BrunoV21 Jul 30, 2025
77299f8
added chainlit dummy auth and data_layer
BrunoV21 Jul 30, 2025
e2111e5
send all
BrunoV21 Jul 30, 2025
2e41f99
updated package requirements
BrunoV21 Jul 31, 2025
2796d8e
added missing col (chainlit latest version)
BrunoV21 Jul 31, 2025
98955c1
addded on chat_resume
BrunoV21 Jul 31, 2025
5287a56
added process_thread initial version
BrunoV21 Aug 3, 2025
6af6979
implemented chat resume logic
BrunoV21 Aug 4, 2025
0159e19
Add validate_paths method to AutoComplete for file path validation us…
BrunoV21 Aug 4, 2025
f8ca81b
Refactor process_thread to remove tool steps without output and reord…
BrunoV21 Aug 4, 2025
88ece19
added TODO
BrunoV21 Aug 4, 2025
69e0f97
updated prompts
BrunoV21 Aug 5, 2025
e4ae58f
added username
BrunoV21 Aug 5, 2025
5bd6903
added parse_steps function
BrunoV21 Aug 5, 2025
d726792
added parse_steps tests
BrunoV21 Aug 5, 2025
0913c00
added STEPS_SYSTEM_PROMPT and first try with planning mode
BrunoV21 Aug 5, 2025
fbb38a1
added stream processor for multi blocks extraction
BrunoV21 Aug 6, 2025
104b4ec
added robustness to apply patch
BrunoV21 Aug 6, 2025
f8d4da3
added initial version of planning agent to ui
BrunoV21 Aug 6, 2025
7443ed3
integrated steps into AgentTide
BrunoV21 Aug 6, 2025
101b37a
added run steps button
BrunoV21 Aug 6, 2025
66a467a
refactored
BrunoV21 Aug 7, 2025
4a04ce2
added dummy task list with steps
BrunoV21 Aug 7, 2025
9a8454c
added support to receive code identifiers
BrunoV21 Aug 8, 2025
98fda5f
added instruccitons template to Step Model
BrunoV21 Aug 8, 2025
d009884
integrated taks list with steps and action buttons into agent tide ui
BrunoV21 Aug 8, 2025
224748e
Updated STEPS system prompt so that generated steps start on 1 instea…
BrunoV21 Aug 8, 2025
85e4da4
removed planning switch
BrunoV21 Aug 8, 2025
9b35c6c
removed escaped sequence
BrunoV21 Aug 8, 2025
0675981
added further rule for .md enumeration likee scenarios
BrunoV21 Aug 8, 2025
9ea4d39
updated roadmap
BrunoV21 Aug 8, 2025
bfb8a66
added agent tide avatars
BrunoV21 Aug 8, 2025
fb3a731
updated gitignore
BrunoV21 Aug 9, 2025
3196517
updated avatars and favicon
BrunoV21 Aug 9, 2025
f77b2ce
updated styles and logo
BrunoV21 Aug 9, 2025
475e611
removed duplicated chainlit.md
BrunoV21 Aug 10, 2025
1b4dc46
added protection to skip unwanted files from context
BrunoV21 Aug 10, 2025
f2cfca5
updated chainlit.md with more AgentTide information
BrunoV21 Aug 10, 2025
9ff4e80
updated the README
BrunoV21 Aug 10, 2025
1ed3827
added nl.json translations
BrunoV21 Aug 10, 2025
583cb3a
updated README with banner
BrunoV21 Aug 10, 2025
2d9f62a
updated manifest.in
BrunoV21 Aug 10, 2025
b59ce76
added starters
BrunoV21 Aug 10, 2025
723f75b
added icons for buttons and added stop buttn placeholder
BrunoV21 Aug 10, 2025
49e9e63
updated starters
BrunoV21 Aug 10, 2025
7440474
added starterts svg icons
BrunoV21 Aug 10, 2025
a02d895
added ocnitnue and delete buttons
BrunoV21 Aug 11, 2025
73b0aa5
moved tide,check_for_updates
BrunoV21 Aug 11, 2025
5af65ce
added robustness to patch_code
BrunoV21 Aug 13, 2025
6d25549
refactored tests
BrunoV21 Aug 13, 2025
d11f6ed
removed old mermaid logic
BrunoV21 Aug 13, 2025
a411fe8
initial version of codebasegraph
BrunoV21 Aug 13, 2025
d0c8c75
added ribustness to apply_patch method
BrunoV21 Aug 13, 2025
1052762
updated .gitignore
BrunoV21 Aug 14, 2025
d984bff
added robustness
BrunoV21 Aug 14, 2025
b37f2b8
prompt update
BrunoV21 Aug 14, 2025
1f45586
removed previous patch to avoid confusion with human introduced chang…
BrunoV21 Aug 14, 2025
12280cb
typo fix
BrunoV21 Aug 14, 2025
a0cfe49
updated STEP_INSTRUCTION_TEMPLATE
BrunoV21 Aug 14, 2025
2d13f6d
improved robustness by protecting againsts singular ' " in the same l…
BrunoV21 Aug 14, 2025
b3e0a63
updated README
BrunoV21 Aug 14, 2025
3a45345
added chainlit commands for review,
BrunoV21 Aug 15, 2025
5967d47
updated chainlit.md
BrunoV21 Aug 15, 2025
e00bb72
updated readme
BrunoV21 Aug 15, 2025
df6f364
updated patch_code
BrunoV21 Aug 16, 2025
afca807
added util functions to capture patch from streamed llm output direct…
BrunoV21 Aug 16, 2025
40ce90b
integrated new pathc code logic into agent tide
BrunoV21 Aug 16, 2025
76c12c1
updated defaults
BrunoV21 Aug 16, 2025
fa204ba
oersisted session_id on agenttide ui
BrunoV21 Aug 16, 2025
d4c5e92
bug fix
BrunoV21 Aug 16, 2025
3bd9d06
empty file patches are now deleted
BrunoV21 Aug 16, 2025
7ebab53
turnned ocmmands into static class var
BrunoV21 Aug 16, 2025
fa1595a
added valid llm check and config procedure and optimzed chat start pr…
BrunoV21 Aug 16, 2025
cb3e096
bound enconding to DEFAULT_ENCODING
BrunoV21 Aug 16, 2025
1490998
added support to pass and store aicore config via agent tide frontend
BrunoV21 Aug 16, 2025
f6eb7b1
updated apply_patch system prompt
BrunoV21 Aug 17, 2025
b136a0e
updated patch.bash file generation method
BrunoV21 Aug 17, 2025
654e832
additional protection
BrunoV21 Aug 17, 2025
942fc8b
propagated session_id
BrunoV21 Aug 17, 2025
f4f4adf
added hf-sapce-demo-app
BrunoV21 Aug 17, 2025
60c5ce1
update agent-tide-demo example for direct git cloning
BrunoV21 Aug 17, 2025
64758a3
added dockerfile and docker-compose for hf space deployment
BrunoV21 Aug 17, 2025
5f10cc6
added action for hf space deployment
BrunoV21 Aug 17, 2025
82de7de
updated apply_patch tests
BrunoV21 Aug 18, 2025
b303b05
refactored tests to make use of temp file
BrunoV21 Aug 19, 2025
56ccf1a
fixed tests
BrunoV21 Aug 19, 2025
d3c9925
updated tests
BrunoV21 Aug 19, 2025
86f42e6
updated requirements
BrunoV21 Aug 19, 2025
05b1abc
updated
BrunoV21 Aug 19, 2025
0a67acd
typo
BrunoV21 Aug 19, 2025
eee3c21
fixed pipeline tests
BrunoV21 Aug 19, 2025
b233eaf
updateed hf_deploy triggers
BrunoV21 Aug 19, 2025
e4edb70
added README.md for hf deployment
BrunoV21 Aug 19, 2025
cc15ff4
updateed hf_deploy triggers
BrunoV21 Aug 19, 2025
8f2f570
updated pipeline
BrunoV21 Aug 19, 2025
038581d
updated teests
BrunoV21 Aug 19, 2025
6a9523a
updated reqs
BrunoV21 Aug 19, 2025
5880cca
updated pipeline
BrunoV21 Aug 19, 2025
d472531
updated for python10 compatilbility
BrunoV21 Aug 19, 2025
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
32 changes: 32 additions & 0 deletions .github/workflows/hf_space_push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Sync Agent Tide Demo to Hugging Face Space
on:
push:
branches: [main]
tags: [ "*" ]
release:
types: [published, created, edited]

workflow_dispatch:

jobs:
sync-to-hub:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
lfs: true

- name: Deploy examples/hf_demo_space to HF Space
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
run: |
cd examples/hf_demo_space
git init --initial-branch=main
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git remote add origin https://McLoviniTtt:$HF_TOKEN@huggingface.co/spaces/McLoviniTtt/AgentTideDemo
git add .
git commit -m "Deploy Agent Tide Demo to HF Space"
git push --force origin main
6 changes: 3 additions & 3 deletions .github/workflows/python_package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ jobs:
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: pytest tests --ignore=tests/agents
run: pytest tests --ignore=tests/agents --ignore=tests/mcp/tools
- name: Install package with agents requirements
run: |
python -m pip install .[agents]
python -m pip install -r requirements-agents.txt
- name: Test agents with pytest
run: pytest tests/agents
run: pytest tests/agents tests/mcp/tools
security:
name: Security Check
runs-on: ubuntu-latest
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,7 @@ storage/
logs/
observability_data/
config/
*.db
.files/

codetide/agents/tide/ui/assets/
10 changes: 10 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
include requirements.txt
include requirements-agents.txt
include docs/assets/codetide-logo.png
include requirements-visualization.txt
include README.md

# Include all files in codetide/agents/tide/ui/.chainlit and public directories (and subdirectories)
recursive-include codetide/agents/tide/ui/.chainlit *
recursive-include codetide/agents/tide/ui/public *
recursive-include codetide/agents/tide/ui *
5 changes: 0 additions & 5 deletions MANIFIEST.in

This file was deleted.

74 changes: 71 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
<div align="center">

<!-- [![Docs](https://img.shields.io/badge/docs-CodeTide.github.io-red)](https://brunov21.github.io/CodeTide/) -->
# <img src="./docs/assets/codetide-logo.png" alt="code-tide-logo" width="35" height="auto"/> CodeTide
<img src="./codetide/agents/tide/ui/public/codetide-banner.png" alt="code-tide-logo" width="900" height="auto"/>



[![GitHub Stars](https://img.shields.io/github/stars/BrunoV21/CodeTide?style=social)](https://github.com/BrunoV21/CodeTide/stargazers)
[![PyPI Downloads](https://static.pepy.tech/badge/CodeTide)](https://pepy.tech/projects/CodeTide)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/CodeTide?style=flat)](https://pypi.org/pypi/codetide/)
[![PyPI - Version](https://img.shields.io/pypi/v/CodeTide?style=flat)](https://pypi.org/pypi/codetide/)
[![Pydantic v2](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydantic/pydantic/main/docs/badge/v2.json)](https://pydantic.dev)
---

**CodeTide** is a fully local, privacy-preserving tool for parsing and understanding Python codebases using symbolic, structural analysis. No internet, no LLMs, no embeddings - just fast, explainable, and deterministic code intelligence.
</div>

---

**CodeTide** is a fully local, privacy-preserving tool for parsing and understanding Python codebases using symbolic, structural analysis. No internet, no LLMs, no embeddings - just fast, explainable, and deterministic code intelligence.


## ✅ Key Features

- ✅ 100% **local & private** - all parsing and querying happens on your machine.
Expand All @@ -20,6 +27,64 @@
- ⚡ Fast, cacheable parsing with smart update detection.
- 🔁 Designed to work alongside tools like Copilot, GPT, and Claude - on your terms.


---
# Entrypoints & Usage

CodeTide provides several entrypoints for interacting with the system via command-line and web UI. These entrypoints are exposed through the `uvx` launcher and require the appropriate extras to be installed.

## CodeTide CLI

To use the main CodeTide CLI:

```sh
uvx --from codetide codetide-cli --help
```
## AgentTide

AgentTide consists of a demo, showing how CodeTide can integrate with LLMs and augment code generation and condebase related workflows. If you ask Tide to describe himself, he will say something like this: I'm the next-generation, precision-driven software engineering agent built on top of CodeTide. You can use it via the command-line interface (CLI) or a beautiful interactive UI.

---

<div align="center">
<!-- [![Docs](https://img.shields.io/badge/docs-CodeTide.github.io-red)](https://brunov21.github.io/CodeTide/) -->
<img src="./codetide/agents/tide/ui/public/agent-tide-demo.gif" alt="agent-tide-demo" width="100%" height="auto"/>
</div>

---

**AgentTide CLI**

To use the AgentTide conversational CLI, you must install the `[agents]` extra and launch via:

```sh
uvx --from codetide[agents] agent-tide
```

This will start an interactive terminal session with AgentTide.

**AgentTide UI**

To use the AgentTide web UI, you must install the `[agents-ui]` extra and launch via:

```sh
uvx --from codetide[agents-ui] agent-tide-ui
```

This will start a web server for the AgentTide UI. Follow the on-screen instructions to interact with the agent in your browser at [http://localhost:9753](http://localhost:9753) (or the port you specified)

### Why Try AgentTide? ([Full Guide & Tips Here](codetide/agents/tide/ui/chainlit.md))

**Local-First & Private:** All code analysis and patching is performed locally. Your code never leaves your machine.
- **Transparent & Stepwise:** See every plan and patch before it's applied. Edit, reorder, or approve steps—you're always in control.
- **Context-Aware:** AgentTide loads only the relevant code identifiers and dependencies for your request, making it fast and precise.
- **Human-in-the-Loop:** After each step, review the patch, provide feedback, or continue—no black-box agent behavior.
- **Patch-Based Editing:** All changes are atomic diffs, not full file rewrites, for maximum clarity and efficiency.

**Usage Tips:**
If you know the exact code context, specify identifiers directly in your request (e.g., `module.submodule.file_withoutextension.object`).
You can request a plan, edit steps, and proceed step-by-step—see the [chainlit.md](codetide/agents/tide/ui/chainlit.md) for full details and advanced workflows!

---

## 🔌 VSCode Extension
Expand Down Expand Up @@ -461,6 +526,9 @@ Here’s what’s next for CodeTide:
~~- 🧭 **Handle relative imports** in Python projects
→ Improve resolution for intra-package navigation.~~

- 🚀 **AgentTideUi Hugging Face Space**
→ We are planning to make AgentTideUi available as a Hugging Face Space, supporting GitHub OAuth for user session and allowing users to provide a repo URL for one-time conversations.

---

## 🤖 Agents Module: AgentTide
Expand Down
16 changes: 14 additions & 2 deletions codetide/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from codetide.core.defaults import (
CODETIDE_ASCII_ART, DEFAULT_SERIALIZATION_PATH, DEFAULT_MAX_CONCURRENT_TASKS,
DEFAULT_BATCH_SIZE, DEFAULT_CACHED_ELEMENTS_FILE, DEFAULT_CACHED_IDS_FILE,
LANGUAGE_EXTENSIONS
LANGUAGE_EXTENSIONS, SKIP_EXTENSIONS
)
from codetide.core.models import CodeFileModel, CodeBase, CodeContextStructure
from codetide.core.common import readFile, writeFile
Expand Down Expand Up @@ -474,6 +474,18 @@ async def check_for_updates(self,
include_cached_ids=kwargs.get("include_cached_ids", False)
)

@staticmethod
def _is_file_content_valid(filepath :Path)->bool:
# Lowercase name for case-insensitive matching
name_lower = filepath.name.lower()

# Skip if extension or full filename is in SKIP_EXTENSIONS
for ext in SKIP_EXTENSIONS:
if name_lower.endswith(ext.lower()):
return False

return True

def _precheck_id_is_file(self, unique_ids : List[str])->Dict[Path, str]:
"""
Preload file contents for the given IDs if they correspond to known files.
Expand All @@ -486,7 +498,7 @@ def _precheck_id_is_file(self, unique_ids : List[str])->Dict[Path, str]:
"""
return {
unique_id: readFile(self.rootpath / unique_id) for unique_id in unique_ids
if self.rootpath / unique_id in self.files
if self.rootpath / unique_id in self.files and self._is_file_content_valid(self.rootpath / unique_id)
}

def get(
Expand Down
179 changes: 179 additions & 0 deletions codetide/agents/data_layer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
try:
from sqlalchemy.orm import declarative_base, relationship, mapped_column
from sqlalchemy import String, Text, ForeignKey, Boolean, Integer
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy.types import TypeDecorator
except ImportError as e:
raise ImportError(
"This module requires 'sqlalchemy' and 'ulid-py'. "
"Install them with: pip install codetide[agents-ui]"
) from e

from datetime import datetime
from sqlalchemy import Select
from ulid import ulid
import asyncio
import json

# SQLite-compatible JSON and UUID types
class GUID(TypeDecorator):
impl = String

def process_bind_param(self, value, dialect):
if value is None:
return None
return str(value)

def process_result_value(self, value, dialect):
return value
class JSONEncodedDict(TypeDecorator):
impl = Text

def process_bind_param(self, value, dialect):
return json.dumps(value) if value is not None else None

def process_result_value(self, value, dialect):
return json.loads(value) if value is not None else None

class JSONEncodedList(TypeDecorator):
impl = Text

def process_bind_param(self, value, dialect):
return json.dumps(value) if value is not None else None

def process_result_value(self, value, dialect):
return json.loads(value) if value is not None else None

Base = declarative_base()

class User(Base):
__tablename__ = "users"
id = mapped_column(GUID, primary_key=True, default=ulid)
identifier = mapped_column(Text, unique=True, nullable=False)
user_metadata = mapped_column("metadata", JSONEncodedDict, nullable=False)
createdAt = mapped_column(Text, default=lambda: datetime.utcnow().isoformat())

class Thread(Base):
__tablename__ = "threads"
id = mapped_column(GUID, primary_key=True, default=ulid)
createdAt = mapped_column(Text, default=lambda: datetime.utcnow().isoformat())
name = mapped_column(Text)
userId = mapped_column(GUID, ForeignKey("users.id", ondelete="CASCADE"))
userIdentifier = mapped_column(Text)
tags = mapped_column(JSONEncodedList)
user_metadata = mapped_column("metadata", JSONEncodedDict)

user = relationship("User", backref="threads")

class Step(Base):
__tablename__ = "steps"
id = mapped_column(GUID, primary_key=True, default=ulid)
name = mapped_column(Text, nullable=False)
type = mapped_column(Text, nullable=False)
threadId = mapped_column(GUID, ForeignKey("threads.id", ondelete="CASCADE"), nullable=False)
parentId = mapped_column(GUID)
streaming = mapped_column(Boolean, nullable=False)
waitForAnswer = mapped_column(Boolean)
isError = mapped_column(Boolean)
user_metadata = mapped_column("metadata", JSONEncodedDict)
tags = mapped_column(JSONEncodedList)
input = mapped_column(Text)
output = mapped_column(Text)
createdAt = mapped_column(Text, default=lambda: datetime.utcnow().isoformat())
command = mapped_column(Text)
start = mapped_column(Text)
end = mapped_column(Text)
generation = mapped_column(JSONEncodedDict)
showInput = mapped_column(Text)
language = mapped_column(Text)
indent = mapped_column(Integer)
defaultOpen = mapped_column(Boolean, default=False)

class Element(Base):
__tablename__ = "elements"
id = mapped_column(GUID, primary_key=True, default=ulid)
threadId = mapped_column(GUID, ForeignKey("threads.id", ondelete="CASCADE"))
type = mapped_column(Text)
url = mapped_column(Text)
chainlitKey = mapped_column(Text)
name = mapped_column(Text, nullable=False)
display = mapped_column(Text)
objectKey = mapped_column(Text)
size = mapped_column(Text)
page = mapped_column(Integer)
language = mapped_column(Text)
forId = mapped_column(GUID)
mime = mapped_column(Text)
props = mapped_column(JSONEncodedDict)

class Feedback(Base):
__tablename__ = "feedbacks"
id = mapped_column(GUID, primary_key=True, default=ulid)
forId = mapped_column(GUID, nullable=False)
threadId = mapped_column(GUID, ForeignKey("threads.id", ondelete="CASCADE"), nullable=False)
value = mapped_column(Integer, nullable=False)
comment = mapped_column(Text)

# class AsyncMessageDB:
# def __init__(self, db_path: str):
# self.db_url = f"sqlite+aiosqlite:///{db_path}"
# self.engine = create_async_engine(self.db_url, echo=False)
# self.async_session = async_sessionmaker(bind=self.engine, class_=AsyncSession, expire_on_commit=False)

# async def init_db(self):
# async with self.engine.begin() as conn:
# await conn.run_sync(Base.user_metadata.create_all)

# async def create_chat(self, name: str) -> Chat:
# async with self.async_session() as session:
# chat = Chat(name=name)
# session.add(chat)
# await session.commit()
# await session.refresh(chat)
# return chat

# async def add_message(self, chat_id: str, role: str, content: str) -> Message:
# async with self.async_session() as session:
# message = Message(chat_id=chat_id, role=role, content=content)
# session.add(message)
# await session.commit()
# await session.refresh(message)
# return message

# async def get_messages_for_chat(self, chat_id: str) -> List[Message]:
# async with self.async_session() as session:
# result = await session.execute(
# select(Message).where(Message.chat_id == chat_id).order_by(Message.timestamp)
# )
# return result.scalars().all()

# async def list_chats(self) -> List[Chat]:
# async with self.async_session() as session:
# result = await session.execute(select(Chat).order_by(Chat.name))
# return result.scalars().all()

# async def main():
# db = AsyncMessageDB(str(Path(os.path.abspath(__file__)).parent / "my_messages.db"))
# await db.init_db()

# chat = await db.create_chat("My First Chat")
# await db.add_message(chat.id, "user", "Hello Assistant!")
# await db.add_message(chat.id, "assistant", "Hello, how can I help you?")

# print(f"Messages for chat '{chat.name}':")
# messages = await db.get_messages_for_chat(chat.id)
# for msg in messages:
# print(f"[{msg.timestamp}] {msg.role.upper()}: {msg.content}")

# print("\nAll chats:")
# chats = await db.list_chats()
# for c in chats:
# print(f"{c.id} — {c.name}")
async def init_db(path: str):
from sqlalchemy.ext.asyncio import async_sessionmaker, AsyncSession
engine = create_async_engine(f"sqlite+aiosqlite:///{path}")
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)

if __name__ == "__main__":
asyncio.run(init_db("database.db"))
Loading