Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ __pycache__
data
docs
tests

4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: CI

on:
push:
branches: [main]
branches: [main, dev]
pull_request:
branches: [main]
branches: [main, dev]

jobs:
python:
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,9 @@ cython_debug/
.abstra/

# Visual Studio Code
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
# and can be added to the global gitignore or merged into this file. However, if you prefer,
# and can be added to the global gitignore or merged into this file. However, if you prefer,
# you could uncomment the following to ignore the entire vscode folder
# .vscode/
# Temporary file for partial code execution
Expand Down
38 changes: 38 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.10
hooks:
- id: ruff
args: [ --fix ]
- id: ruff-format

- repo: local
hooks:
- id: frontend-prettier
name: Frontend Prettier
entry: npm --prefix frontend run format
language: system
files: ^frontend/.*\.([jt]sx?|css|json)$
pass_filenames: false

- id: frontend-eslint
name: Frontend ESLint
entry: npm --prefix frontend run lint
language: system
files: ^frontend/.*\.([jt]sx?)$
pass_filenames: false

- id: mypy
name: mypy
entry: uv run mypy src/awaaz
language: system
files: ^src/awaaz/.*\.py$
pass_filenames: false
1 change: 1 addition & 0 deletions alembic/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
calling code may pass an existing connection via ``config.attributes[
"connection"]`` to share a single transaction.
"""

import asyncio
from logging.config import fileConfig

Expand Down
182 changes: 94 additions & 88 deletions alembic/versions/9cbf7db8429b_initial_schema.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""initial schema

Revision ID: 9cbf7db8429b
Revises:
Revises:
Create Date: 2026-06-27 20:22:36.367761

"""

from collections.abc import Sequence

import sqlalchemy as sa
Expand All @@ -13,113 +14,118 @@
from alembic import op

# revision identifiers, used by Alembic.
revision: str = '9cbf7db8429b'
revision: str = "9cbf7db8429b"
down_revision: str | None = None
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('collections',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.PrimaryKeyConstraint('id')
op.create_table(
"collections",
sa.Column("id", sa.String(length=36), nullable=False),
sa.Column("name", sa.String(length=255), nullable=False),
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
sa.PrimaryKeyConstraint("id"),
)
with op.batch_alter_table('collections', schema=None) as batch_op:
batch_op.create_index(batch_op.f('ix_collections_name'), ['name'], unique=True)

op.create_table('documents',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('title', sa.String(length=255), nullable=False),
sa.Column('source_filename', sa.String(length=255), nullable=True),
sa.Column('text', sa.Text(), nullable=False),
sa.Column('revision', sa.Integer(), nullable=False),
sa.Column('author', sa.String(length=255), nullable=True),
sa.Column('series', sa.String(length=255), nullable=True),
sa.Column('tags', sa.String(length=500), nullable=True),
sa.Column('cover_path', sa.Text(), nullable=True),
sa.Column('metadata_json', sqlite.JSON(), nullable=True),
sa.Column('word_count', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.PrimaryKeyConstraint('id')
with op.batch_alter_table("collections", schema=None) as batch_op:
batch_op.create_index(batch_op.f("ix_collections_name"), ["name"], unique=True)

op.create_table(
"documents",
sa.Column("id", sa.String(length=36), nullable=False),
sa.Column("title", sa.String(length=255), nullable=False),
sa.Column("source_filename", sa.String(length=255), nullable=True),
sa.Column("text", sa.Text(), nullable=False),
sa.Column("revision", sa.Integer(), nullable=False),
sa.Column("author", sa.String(length=255), nullable=True),
sa.Column("series", sa.String(length=255), nullable=True),
sa.Column("tags", sa.String(length=500), nullable=True),
sa.Column("cover_path", sa.Text(), nullable=True),
sa.Column("metadata_json", sqlite.JSON(), nullable=True),
sa.Column("word_count", sa.Integer(), nullable=False),
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
sa.PrimaryKeyConstraint("id"),
)
with op.batch_alter_table('documents', schema=None) as batch_op:
batch_op.create_index(batch_op.f('ix_documents_author'), ['author'], unique=False)
batch_op.create_index(batch_op.f('ix_documents_series'), ['series'], unique=False)

op.create_table('document_collections',
sa.Column('document_id', sa.String(length=36), nullable=False),
sa.Column('collection_id', sa.String(length=36), nullable=False),
sa.ForeignKeyConstraint(['collection_id'], ['collections.id'], ondelete='CASCADE'),
sa.ForeignKeyConstraint(['document_id'], ['documents.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('document_id', 'collection_id')
with op.batch_alter_table("documents", schema=None) as batch_op:
batch_op.create_index(batch_op.f("ix_documents_author"), ["author"], unique=False)
batch_op.create_index(batch_op.f("ix_documents_series"), ["series"], unique=False)

op.create_table(
"document_collections",
sa.Column("document_id", sa.String(length=36), nullable=False),
sa.Column("collection_id", sa.String(length=36), nullable=False),
sa.ForeignKeyConstraint(["collection_id"], ["collections.id"], ondelete="CASCADE"),
sa.ForeignKeyConstraint(["document_id"], ["documents.id"], ondelete="CASCADE"),
sa.PrimaryKeyConstraint("document_id", "collection_id"),
)
op.create_table('jobs',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('document_id', sa.String(length=36), nullable=False),
sa.Column('document_revision', sa.Integer(), nullable=False),
sa.Column('status', sa.String(length=32), nullable=False),
sa.Column('backend', sa.String(length=32), nullable=False),
sa.Column('model', sa.String(length=255), nullable=False),
sa.Column('voice', sa.String(length=255), nullable=False),
sa.Column('speed', sa.Float(), nullable=False),
sa.Column('chunking_mode', sa.String(length=32), nullable=False),
sa.Column('character_limit', sa.Integer(), nullable=False),
sa.Column('error', sa.Text(), nullable=True),
sa.Column('output_path', sa.Text(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(['document_id'], ['documents.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id')
op.create_table(
"jobs",
sa.Column("id", sa.String(length=36), nullable=False),
sa.Column("document_id", sa.String(length=36), nullable=False),
sa.Column("document_revision", sa.Integer(), nullable=False),
sa.Column("status", sa.String(length=32), nullable=False),
sa.Column("backend", sa.String(length=32), nullable=False),
sa.Column("model", sa.String(length=255), nullable=False),
sa.Column("voice", sa.String(length=255), nullable=False),
sa.Column("speed", sa.Float(), nullable=False),
sa.Column("chunking_mode", sa.String(length=32), nullable=False),
sa.Column("character_limit", sa.Integer(), nullable=False),
sa.Column("error", sa.Text(), nullable=True),
sa.Column("output_path", sa.Text(), nullable=True),
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(["document_id"], ["documents.id"], ondelete="CASCADE"),
sa.PrimaryKeyConstraint("id"),
)
with op.batch_alter_table('jobs', schema=None) as batch_op:
batch_op.create_index(batch_op.f('ix_jobs_status'), ['status'], unique=False)

op.create_table('chunks',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('job_id', sa.String(length=36), nullable=False),
sa.Column('position', sa.Integer(), nullable=False),
sa.Column('text', sa.Text(), nullable=False),
sa.Column('status', sa.String(length=32), nullable=False),
sa.Column('attempts', sa.Integer(), nullable=False),
sa.Column('audio_path', sa.Text(), nullable=True),
sa.Column('error', sa.Text(), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(['job_id'], ['jobs.id'], ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('job_id', 'position')
with op.batch_alter_table("jobs", schema=None) as batch_op:
batch_op.create_index(batch_op.f("ix_jobs_status"), ["status"], unique=False)

op.create_table(
"chunks",
sa.Column("id", sa.String(length=36), nullable=False),
sa.Column("job_id", sa.String(length=36), nullable=False),
sa.Column("position", sa.Integer(), nullable=False),
sa.Column("text", sa.Text(), nullable=False),
sa.Column("status", sa.String(length=32), nullable=False),
sa.Column("attempts", sa.Integer(), nullable=False),
sa.Column("audio_path", sa.Text(), nullable=True),
sa.Column("error", sa.Text(), nullable=True),
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(["job_id"], ["jobs.id"], ondelete="CASCADE"),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("job_id", "position"),
)
with op.batch_alter_table('chunks', schema=None) as batch_op:
batch_op.create_index(batch_op.f('ix_chunks_job_id'), ['job_id'], unique=False)
batch_op.create_index(batch_op.f('ix_chunks_status'), ['status'], unique=False)
with op.batch_alter_table("chunks", schema=None) as batch_op:
batch_op.create_index(batch_op.f("ix_chunks_job_id"), ["job_id"], unique=False)
batch_op.create_index(batch_op.f("ix_chunks_status"), ["status"], unique=False)

# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('chunks', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_chunks_status'))
batch_op.drop_index(batch_op.f('ix_chunks_job_id'))
with op.batch_alter_table("chunks", schema=None) as batch_op:
batch_op.drop_index(batch_op.f("ix_chunks_status"))
batch_op.drop_index(batch_op.f("ix_chunks_job_id"))

op.drop_table('chunks')
with op.batch_alter_table('jobs', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_jobs_status'))
op.drop_table("chunks")
with op.batch_alter_table("jobs", schema=None) as batch_op:
batch_op.drop_index(batch_op.f("ix_jobs_status"))

op.drop_table('jobs')
op.drop_table('document_collections')
with op.batch_alter_table('documents', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_documents_series'))
batch_op.drop_index(batch_op.f('ix_documents_author'))
op.drop_table("jobs")
op.drop_table("document_collections")
with op.batch_alter_table("documents", schema=None) as batch_op:
batch_op.drop_index(batch_op.f("ix_documents_series"))
batch_op.drop_index(batch_op.f("ix_documents_author"))

op.drop_table('documents')
with op.batch_alter_table('collections', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_collections_name'))
op.drop_table("documents")
with op.batch_alter_table("collections", schema=None) as batch_op:
batch_op.drop_index(batch_op.f("ix_collections_name"))

op.drop_table('collections')
op.drop_table("collections")
# ### end Alembic commands ###
1 change: 0 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,3 @@ input above configured backend limit.
Job states: `queued`, `running`, `paused`, `failed`, `cancelled`, `completed`. Chunk states:
`pending`, `processing`, `failed`, `completed`. Worker startup resets abandoned `processing`
chunks to `pending`. Atomic file replacement prevents partial WAV checkpoints.

1 change: 0 additions & 1 deletion frontend/.dockerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
node_modules
dist
coverage

1 change: 0 additions & 1 deletion frontend/nginx.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,3 @@ server {
try_files $uri $uri/ /index.html;
}
}

Loading