Spaces:
Build error
Build error
Merge pull request #800 from AlphaSphereDotAI/hf
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .deepsource.toml +22 -0
- .dockerignore +9 -0
- .envrc +6 -0
- .gitattributes +4 -35
- .github/lint/.hadolint.yaml +6 -0
- .github/lint/.ls-lint.yaml +8 -0
- .github/lint/.markdownlint.yaml +3 -0
- .github/lint/.ruff.toml +24 -0
- .github/lint/.taplo.toml +7 -0
- .github/lint/.trivy.yaml +1 -0
- .github/lint/.trivyignore.yaml +2 -0
- .github/lint/.yamlfix.toml +3 -0
- .github/lint/.yamllint.yaml +28 -0
- .github/mergify.yml +127 -0
- .github/renovate.json +25 -0
- .github/workflows/.docker.yaml +306 -0
- .github/workflows/.lint.yaml +363 -0
- .github/workflows/build.yaml +86 -0
- .github/workflows/ci_tools.yaml +106 -0
- .github/workflows/release.yaml +70 -0
- .github/workflows/test.yaml +76 -0
- .github/workflows/version.yaml +45 -0
- .gitignore +12 -0
- .idea/.gitignore +12 -0
- .idea/chattr.iml +15 -0
- .idea/inspectionProfiles/Project_Default.xml +237 -0
- .idea/inspectionProfiles/profiles_settings.xml +6 -0
- .idea/misc.xml +13 -0
- .idea/modules.xml +8 -0
- .idea/vcs.xml +6 -0
- .pre-commit-config.yaml +118 -0
- .sonarlint/connectedMode.json +5 -0
- .vscode/launch.json +19 -0
- .vscode/tasks.json +15 -0
- .zed/tasks.json +24 -0
- AGENTS.md +133 -0
- Dockerfile +32 -0
- README.md +34 -8
- assets/image/Einstein.jpg +3 -0
- assets/image/Napoleon.jpg +0 -0
- assets/prompts/template.poml +30 -0
- docker-compose-dev.yaml +97 -0
- docker-compose.yaml +126 -0
- mcp.json +40 -0
- pyproject.toml +41 -0
- src/chattr/__init__.py +8 -0
- src/chattr/__main__.py +22 -0
- src/chattr/app/__init__.py +3 -0
- src/chattr/app/builder.py +323 -0
- src/chattr/app/logger.py +19 -0
.deepsource.toml
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version = 1
|
| 2 |
+
|
| 3 |
+
[[analyzers]]
|
| 4 |
+
name = "shell"
|
| 5 |
+
|
| 6 |
+
[[analyzers]]
|
| 7 |
+
dependency_file_paths = ["pyproject.toml"]
|
| 8 |
+
name = "python"
|
| 9 |
+
|
| 10 |
+
[analyzers.meta]
|
| 11 |
+
additional_builtins = ["_", "pretty_output"]
|
| 12 |
+
runtime_version = "3.x.x"
|
| 13 |
+
type_checker = "mypy"
|
| 14 |
+
|
| 15 |
+
[[analyzers]]
|
| 16 |
+
name = "docker"
|
| 17 |
+
|
| 18 |
+
[[analyzers]]
|
| 19 |
+
name = "secrets"
|
| 20 |
+
|
| 21 |
+
[[transformers]]
|
| 22 |
+
name = "ruff"
|
.dockerignore
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
**/__pycache__/
|
| 2 |
+
.deepsource.toml
|
| 3 |
+
.env
|
| 4 |
+
.github/
|
| 5 |
+
.idea/
|
| 6 |
+
.mypy_cache/
|
| 7 |
+
.ruff_cache/
|
| 8 |
+
.venv/
|
| 9 |
+
.vscode/
|
.envrc
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export MODEL__URL=${MODEL__URL:-https://generativelanguage.googleapis.com/v1beta/openai}
|
| 2 |
+
export MODEL__NAME=${MODEL__NAME:-gemini-2.5-flash}
|
| 3 |
+
export MODEL__API_KEY=${GOOGLE_API_KEY}
|
| 4 |
+
export VECTOR_DATABASE__URL=http://localhost:6333
|
| 5 |
+
export VECTOR_DATABASE__NAME=main
|
| 6 |
+
export CHARACTER__NAME=Napoleon
|
.gitattributes
CHANGED
|
@@ -1,35 +1,4 @@
|
|
| 1 |
-
|
| 2 |
-
*.
|
| 3 |
-
*.
|
| 4 |
-
*.
|
| 5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
| 1 |
+
* text=auto eol=lf
|
| 2 |
+
*.jpg filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.github/lint/.hadolint.yaml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
trustedRegistries:
|
| 2 |
+
- docker.io
|
| 3 |
+
- ghcr.io
|
| 4 |
+
- cgr.dev
|
| 5 |
+
ignored:
|
| 6 |
+
- DL3018
|
.github/lint/.ls-lint.yaml
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
ls:
|
| 2 |
+
.py: snake_case
|
| 3 |
+
.yaml: snake_case | kebab-case
|
| 4 |
+
.yml: snake_case | kebab-case
|
| 5 |
+
.toml: snake_case
|
| 6 |
+
.md: SCREAMING_SNAKE_CASE
|
| 7 |
+
ignore:
|
| 8 |
+
- .git
|
.github/lint/.markdownlint.yaml
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
$schema: https://raw.githubusercontent.com/DavidAnson/markdownlint/main/schema/markdownlint-config-schema-strict.json
|
| 2 |
+
line-length:
|
| 3 |
+
tables: false
|
.github/lint/.ruff.toml
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
indent-width = 4
|
| 2 |
+
line-length = 88
|
| 3 |
+
target-version = "py313"
|
| 4 |
+
|
| 5 |
+
[lint]
|
| 6 |
+
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
| 7 |
+
fixable = ["ALL"]
|
| 8 |
+
ignore = ["D100", "D105", "D107", "D212", "D413", "SIM117"]
|
| 9 |
+
select = ["ALL"]
|
| 10 |
+
unfixable = []
|
| 11 |
+
|
| 12 |
+
[lint.isort]
|
| 13 |
+
combine-as-imports = true
|
| 14 |
+
|
| 15 |
+
[lint.per-file-ignores]
|
| 16 |
+
"test_app.py" = ["INP001", "S101"]
|
| 17 |
+
|
| 18 |
+
[format]
|
| 19 |
+
docstring-code-format = false
|
| 20 |
+
docstring-code-line-length = "dynamic"
|
| 21 |
+
indent-style = "space"
|
| 22 |
+
line-ending = "lf"
|
| 23 |
+
quote-style = "double"
|
| 24 |
+
skip-magic-trailing-comma = false
|
.github/lint/.taplo.toml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
exclude = [".venv/**"]
|
| 2 |
+
[formatting]
|
| 3 |
+
indent_entries = true
|
| 4 |
+
indent_tables = true
|
| 5 |
+
reorder_arrays = true
|
| 6 |
+
reorder_inline_tables = true
|
| 7 |
+
reorder_keys = true
|
.github/lint/.trivy.yaml
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
ignorefile: .github/lint/.trivyignore.yaml
|
.github/lint/.trivyignore.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
misconfigurations:
|
| 2 |
+
- id: AVD-DS-0026
|
.github/lint/.yamlfix.toml
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
comments_min_spaces_from_content = 1
|
| 2 |
+
explicit_start = false
|
| 3 |
+
sequence_style = 'block_style'
|
.github/lint/.yamllint.yaml
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
extends: default
|
| 2 |
+
rules:
|
| 3 |
+
braces:
|
| 4 |
+
level: warning
|
| 5 |
+
max-spaces-inside: 1
|
| 6 |
+
brackets:
|
| 7 |
+
level: warning
|
| 8 |
+
max-spaces-inside: 1
|
| 9 |
+
colons:
|
| 10 |
+
level: warning
|
| 11 |
+
commas:
|
| 12 |
+
level: warning
|
| 13 |
+
comments: disable
|
| 14 |
+
comments-indentation: disable
|
| 15 |
+
document-start: disable
|
| 16 |
+
empty-lines:
|
| 17 |
+
level: warning
|
| 18 |
+
hyphens:
|
| 19 |
+
level: warning
|
| 20 |
+
indentation:
|
| 21 |
+
level: warning
|
| 22 |
+
indent-sequences: consistent
|
| 23 |
+
line-length:
|
| 24 |
+
level: warning
|
| 25 |
+
allow-non-breakable-inline-mappings: true
|
| 26 |
+
max: 140
|
| 27 |
+
truthy: disable
|
| 28 |
+
key-duplicates: enable
|
.github/mergify.yml
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
pull_request_rules:
|
| 2 |
+
- name: Automatically queue pre-commit Updates
|
| 3 |
+
conditions:
|
| 4 |
+
- files ~= .pre-commit-config.yaml
|
| 5 |
+
- author = renovate[bot]
|
| 6 |
+
actions:
|
| 7 |
+
queue:
|
| 8 |
+
label:
|
| 9 |
+
add:
|
| 10 |
+
- pre-commit
|
| 11 |
+
- name: Automatically queue Dockerfile Updates
|
| 12 |
+
conditions:
|
| 13 |
+
- files ~= Dockerfile
|
| 14 |
+
- author = renovate[bot]
|
| 15 |
+
- check-success = Test Image / API Test
|
| 16 |
+
actions:
|
| 17 |
+
queue:
|
| 18 |
+
- name: Automatically label Dockerfile Updates
|
| 19 |
+
conditions:
|
| 20 |
+
- files ~= Dockerfile
|
| 21 |
+
- author = renovate[bot]
|
| 22 |
+
actions:
|
| 23 |
+
label:
|
| 24 |
+
add:
|
| 25 |
+
- docker
|
| 26 |
+
- name: Automatically queue Github Actions Updates
|
| 27 |
+
conditions:
|
| 28 |
+
- files ~= ^.github/workflows
|
| 29 |
+
- author = renovate[bot]
|
| 30 |
+
actions:
|
| 31 |
+
queue:
|
| 32 |
+
label:
|
| 33 |
+
add:
|
| 34 |
+
- github-actions
|
| 35 |
+
- name: Automatically queue valid Python Dependency Updates
|
| 36 |
+
conditions:
|
| 37 |
+
- files ~= ^(uv.lock|pyproject.toml)$
|
| 38 |
+
- author = renovate[bot]
|
| 39 |
+
- and:
|
| 40 |
+
- check-success = Check Dependency Compatibility
|
| 41 |
+
- check-success = Test Image / API Test
|
| 42 |
+
actions:
|
| 43 |
+
queue:
|
| 44 |
+
- name: Automatically label Python Dependency Updates
|
| 45 |
+
conditions:
|
| 46 |
+
- files ~= ^(uv.lock|pyproject.toml)$
|
| 47 |
+
- author = renovate[bot]
|
| 48 |
+
actions:
|
| 49 |
+
label:
|
| 50 |
+
add:
|
| 51 |
+
- uv
|
| 52 |
+
- python
|
| 53 |
+
- dependencies
|
| 54 |
+
- name: Automatically queue Docker Compose Updates
|
| 55 |
+
conditions:
|
| 56 |
+
- files ~= ^(docker-compose-dev.yaml|docker-compose.yaml)$
|
| 57 |
+
- author = renovate[bot]
|
| 58 |
+
actions:
|
| 59 |
+
queue:
|
| 60 |
+
label:
|
| 61 |
+
add:
|
| 62 |
+
- docker-compose
|
| 63 |
+
- name: Merge pull request when the configuration of Mergify is valid
|
| 64 |
+
conditions:
|
| 65 |
+
- author = MH0386
|
| 66 |
+
- 'title = ci(Mergify): configuration update'
|
| 67 |
+
- head = mergify/MH0386/config-update
|
| 68 |
+
actions:
|
| 69 |
+
merge:
|
| 70 |
+
- name: Comment when a pull request is merged
|
| 71 |
+
conditions:
|
| 72 |
+
- merged
|
| 73 |
+
actions:
|
| 74 |
+
delete_head_branch:
|
| 75 |
+
comment:
|
| 76 |
+
message: >-
|
| 77 |
+
Thank you for your contribution @{{author}}! Your pull request has been
|
| 78 |
+
merged.
|
| 79 |
+
- name: Comment if there is a conflict
|
| 80 |
+
conditions:
|
| 81 |
+
- conflict
|
| 82 |
+
actions:
|
| 83 |
+
comment:
|
| 84 |
+
message: Hi @{{author}}, Your PR is in conflict and cannot be merged.
|
| 85 |
+
label:
|
| 86 |
+
add:
|
| 87 |
+
- conflict
|
| 88 |
+
- name: Automatic update of the pull requests
|
| 89 |
+
conditions:
|
| 90 |
+
- -merged
|
| 91 |
+
actions:
|
| 92 |
+
update:
|
| 93 |
+
- name: Add a queue label when PR is queued
|
| 94 |
+
conditions:
|
| 95 |
+
- queue-position > 0
|
| 96 |
+
actions:
|
| 97 |
+
label:
|
| 98 |
+
toggle:
|
| 99 |
+
- merge-queued
|
| 100 |
+
- name: Notify when a PR is removed from the queue
|
| 101 |
+
conditions:
|
| 102 |
+
- queue-dequeue-reason != none
|
| 103 |
+
- queue-dequeue-reason != pr-merged
|
| 104 |
+
actions:
|
| 105 |
+
comment:
|
| 106 |
+
message: >-
|
| 107 |
+
Hey @{{author}}, your pull request has been dequeued due to the following
|
| 108 |
+
reason: {{queue_dequeue_reason}}.
|
| 109 |
+
Sorry about that, but you can requeue the PR by using `@mergifyio requeue`
|
| 110 |
+
if you think this was a mistake.
|
| 111 |
+
queue_rules:
|
| 112 |
+
- name: default
|
| 113 |
+
update_method: merge
|
| 114 |
+
allow_queue_branch_edit: true
|
| 115 |
+
queue_branch_merge_method: fast-forward
|
| 116 |
+
queue_conditions:
|
| 117 |
+
- and:
|
| 118 |
+
- 'check-success = DeepSource: Secrets'
|
| 119 |
+
- 'check-success = DeepSource: Python'
|
| 120 |
+
- 'check-success = DeepSource: pyproject.toml'
|
| 121 |
+
- 'check-success = DeepSource: Docker'
|
| 122 |
+
- check-success = CodeFactor
|
| 123 |
+
- check-success = GitGuardian Security Checks
|
| 124 |
+
- check-success = SonarCloud
|
| 125 |
+
- check-success = CodeQL
|
| 126 |
+
- check-success = Lint / UV Lock Check
|
| 127 |
+
- check-success = Lint / TruffleHog
|
.github/renovate.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
| 3 |
+
"dependencyDashboardOSVVulnerabilitySummary": "all",
|
| 4 |
+
"extends": [
|
| 5 |
+
"config:best-practices"
|
| 6 |
+
],
|
| 7 |
+
"lockFileMaintenance": {
|
| 8 |
+
"enabled": true
|
| 9 |
+
},
|
| 10 |
+
"osvVulnerabilityAlerts": true,
|
| 11 |
+
"packageRules": [
|
| 12 |
+
{
|
| 13 |
+
"matchManagers": [
|
| 14 |
+
"pep621"
|
| 15 |
+
],
|
| 16 |
+
"matchPackageNames": [
|
| 17 |
+
"*"
|
| 18 |
+
],
|
| 19 |
+
"rangeStrategy": "bump"
|
| 20 |
+
}
|
| 21 |
+
],
|
| 22 |
+
"pre-commit": {
|
| 23 |
+
"enabled": true
|
| 24 |
+
}
|
| 25 |
+
}
|
.github/workflows/.docker.yaml
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Docker Image
|
| 2 |
+
on:
|
| 3 |
+
workflow_call:
|
| 4 |
+
inputs:
|
| 5 |
+
is_test:
|
| 6 |
+
type: boolean
|
| 7 |
+
required: true
|
| 8 |
+
description: Test Mode
|
| 9 |
+
registry:
|
| 10 |
+
type: string
|
| 11 |
+
required: true
|
| 12 |
+
description: Registry
|
| 13 |
+
install_source:
|
| 14 |
+
type: string
|
| 15 |
+
required: true
|
| 16 |
+
description: Source to install from (e.g., PyPI Package or Git source)
|
| 17 |
+
permissions:
|
| 18 |
+
contents: read
|
| 19 |
+
packages: write
|
| 20 |
+
attestations: write
|
| 21 |
+
id-token: write
|
| 22 |
+
actions: read
|
| 23 |
+
security-events: write
|
| 24 |
+
jobs:
|
| 25 |
+
check_dockerfile:
|
| 26 |
+
name: Check Dockerfile
|
| 27 |
+
runs-on: ubuntu-latest
|
| 28 |
+
if: ${{ inputs.is_test }}
|
| 29 |
+
environment:
|
| 30 |
+
name: code_quality
|
| 31 |
+
steps:
|
| 32 |
+
- name: Checkout repository
|
| 33 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 34 |
+
- name: Check Dockerfile
|
| 35 |
+
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
| 36 |
+
id: dockerfile_lint
|
| 37 |
+
with:
|
| 38 |
+
call: check
|
| 39 |
+
- name: Job Summary
|
| 40 |
+
uses: jazanne/job-summary-action@690eb386a0b86fe4da7c6f0e543e61330ff09f06 # v1.0.0
|
| 41 |
+
if: success() || failure()
|
| 42 |
+
with:
|
| 43 |
+
summary: |
|
| 44 |
+
## Dockerfile Check
|
| 45 |
+
- **Status**: ${{ steps.dockerfile_lint.outcome == 'success' && ':white_check_mark:' || ':x:' }}
|
| 46 |
+
build_image:
|
| 47 |
+
name: Build and push Docker image to ${{ inputs.registry }}
|
| 48 |
+
needs: check_dockerfile
|
| 49 |
+
if: ${{ always() && !cancelled() && !failure() }}
|
| 50 |
+
runs-on: ubuntu-latest
|
| 51 |
+
outputs:
|
| 52 |
+
image_tag: ${{ steps.tag.outputs.TAG }}
|
| 53 |
+
environment:
|
| 54 |
+
name: docker_image
|
| 55 |
+
url: ${{inputs.registry}}/${{github.repository}}
|
| 56 |
+
steps:
|
| 57 |
+
- name: Free Disk Space
|
| 58 |
+
uses: endersonmenezes/free-disk-space@e6ed9b02e683a3b55ed0252f1ee469ce3b39a885 # v3.1.0
|
| 59 |
+
with:
|
| 60 |
+
remove_android: true
|
| 61 |
+
remove_dotnet: true
|
| 62 |
+
remove_haskell: true
|
| 63 |
+
remove_tool_cache: true
|
| 64 |
+
remove_swap: true
|
| 65 |
+
remove_packages_one_command: true
|
| 66 |
+
rm_cmd: rmz
|
| 67 |
+
remove_folders: >-
|
| 68 |
+
/usr/share /usr/local/lib /usr/local/share
|
| 69 |
+
/usr/local
|
| 70 |
+
- name: Checkout repository
|
| 71 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 72 |
+
- name: Get Python version from pyproject.toml
|
| 73 |
+
id: get_python_version
|
| 74 |
+
uses: mikefarah/yq@065b200af9851db0d5132f50bc10b1406ea5c0a8 # v4.50.1
|
| 75 |
+
with:
|
| 76 |
+
cmd: yq -roy '.project.requires-python' pyproject.toml
|
| 77 |
+
- name: Log in to ${{ inputs.registry }} Registry
|
| 78 |
+
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
| 79 |
+
with:
|
| 80 |
+
registry: ${{ inputs.registry }}
|
| 81 |
+
username: mh0386
|
| 82 |
+
password: ${{ inputs.registry == 'ghcr.io' && secrets.GH_TOKEN || inputs.registry == 'docker.io' && secrets.TOKEN_KEY_DOCKER }}
|
| 83 |
+
- name: Set up QEMU
|
| 84 |
+
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
| 85 |
+
- name: Set up Docker Buildx
|
| 86 |
+
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
| 87 |
+
- name: Docker meta
|
| 88 |
+
id: meta
|
| 89 |
+
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
|
| 90 |
+
with:
|
| 91 |
+
images: ${{ inputs.registry }}/${{ github.repository }}
|
| 92 |
+
tags: |
|
| 93 |
+
type=raw,value=latest,enable=${{ github.event_name == 'push' && contains(github.ref, 'refs/tags/') }}
|
| 94 |
+
type=ref,event=pr,prefix={{sha}}-pr-
|
| 95 |
+
type=ref,event=tag
|
| 96 |
+
type=ref,event=branch
|
| 97 |
+
- name: Build and Push to ${{ inputs.registry }}
|
| 98 |
+
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
|
| 99 |
+
id: push
|
| 100 |
+
with:
|
| 101 |
+
push: true
|
| 102 |
+
sbom: true
|
| 103 |
+
tags: ${{ steps.meta.outputs.tags }}
|
| 104 |
+
labels: ${{ steps.meta.outputs.labels }}
|
| 105 |
+
annotations: ${{ steps.meta.outputs.annotations }}
|
| 106 |
+
build-args: |
|
| 107 |
+
INSTALL_SOURCE=${{ inputs.install_source }}
|
| 108 |
+
PYTHON_VERSION=${{ steps.get_python_version.outputs.result }}
|
| 109 |
+
env:
|
| 110 |
+
DOCKER_CONTENT_TRUST: '1'
|
| 111 |
+
- name: Generate artifact attestation
|
| 112 |
+
uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3.2.0
|
| 113 |
+
if: ${{ inputs.is_test == false }}
|
| 114 |
+
with:
|
| 115 |
+
subject-name: ${{ inputs.registry == 'docker.io' && 'index.docker.io' || inputs.registry }}/${{github.repository}}
|
| 116 |
+
subject-digest: ${{ steps.push.outputs.digest }}
|
| 117 |
+
push-to-registry: true
|
| 118 |
+
- name: Update Docker Hub Description
|
| 119 |
+
if: ${{ inputs.registry == 'docker.io' }}
|
| 120 |
+
uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5.0.0
|
| 121 |
+
with:
|
| 122 |
+
username: mh0386
|
| 123 |
+
password: ${{ secrets.TOKEN_KEY_DOCKER }}
|
| 124 |
+
repository: ${{ github.repository }}
|
| 125 |
+
short-description: ${{ github.event.repository.description }}
|
| 126 |
+
enable-url-completion: true
|
| 127 |
+
- name: Export tag for Testing and Scanning
|
| 128 |
+
id: tag
|
| 129 |
+
run: echo "TAG=$(echo "${{ steps.meta.outputs.tags }}" | tail -n 1)" >> $GITHUB_OUTPUT
|
| 130 |
+
docker_scout:
|
| 131 |
+
name: Docker Scout CVEs
|
| 132 |
+
needs: build_image
|
| 133 |
+
runs-on: ubuntu-latest
|
| 134 |
+
environment:
|
| 135 |
+
name: container_health
|
| 136 |
+
steps:
|
| 137 |
+
- name: Docker Scout
|
| 138 |
+
uses: docker/scout-action@f8c776824083494ab0d56b8105ba2ca85c86e4de # v1.18.2
|
| 139 |
+
with:
|
| 140 |
+
command: cves
|
| 141 |
+
dockerhub-user: mh0386
|
| 142 |
+
dockerhub-password: ${{ secrets.TOKEN_KEY_DOCKER }}
|
| 143 |
+
image: ${{ needs.build_image.outputs.image_tag }}
|
| 144 |
+
github-token: ${{ secrets.GH_TOKEN }}
|
| 145 |
+
trufflehog:
|
| 146 |
+
name: TruffleHog
|
| 147 |
+
runs-on: ubuntu-latest
|
| 148 |
+
needs: build_image
|
| 149 |
+
environment:
|
| 150 |
+
name: container_health
|
| 151 |
+
steps:
|
| 152 |
+
- name: Install trufflehog
|
| 153 |
+
uses: jaxxstorm/action-install-gh-release@6096f2a2bbfee498ced520b6922ac2c06e990ed2 # v2.1.0
|
| 154 |
+
with:
|
| 155 |
+
repo: trufflesecurity/trufflehog
|
| 156 |
+
cache: enable
|
| 157 |
+
- name: Docker Secret Scanning
|
| 158 |
+
run: >-
|
| 159 |
+
trufflehog docker --image ${{needs.build_image.outputs.image_tag}}
|
| 160 |
+
--fail --github-actions --results=verified --log-level=4 --no-update
|
| 161 |
+
syft:
|
| 162 |
+
name: Syft
|
| 163 |
+
runs-on: ubuntu-latest
|
| 164 |
+
needs: build_image
|
| 165 |
+
environment:
|
| 166 |
+
name: container_health
|
| 167 |
+
permissions:
|
| 168 |
+
contents: write
|
| 169 |
+
steps:
|
| 170 |
+
- name: SBOM Generation
|
| 171 |
+
uses: anchore/sbom-action@deef08a0db64bfad603422135db61477b16cef56 # v0.22.1
|
| 172 |
+
with:
|
| 173 |
+
image: ${{ needs.build_image.outputs.image_tag }}
|
| 174 |
+
dependency-snapshot: true
|
| 175 |
+
output-file: ${{ github.event.repository.name }}-sbom.json
|
| 176 |
+
format: syft-json
|
| 177 |
+
grype:
|
| 178 |
+
name: Grype
|
| 179 |
+
needs: build_image
|
| 180 |
+
runs-on: ubuntu-latest
|
| 181 |
+
environment:
|
| 182 |
+
name: container_health
|
| 183 |
+
steps:
|
| 184 |
+
- name: Scan image
|
| 185 |
+
uses: anchore/scan-action@8d2fce09422cd6037e577f4130e9b925e9a37175 # v7.3.1
|
| 186 |
+
id: scan
|
| 187 |
+
with:
|
| 188 |
+
image: ${{ needs.build_image.outputs.image_tag }}
|
| 189 |
+
cache-db: true
|
| 190 |
+
- name: upload Anchore scan SARIF report
|
| 191 |
+
if: success() || failure()
|
| 192 |
+
uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
|
| 193 |
+
with:
|
| 194 |
+
sarif_file: ${{ steps.scan.outputs.sarif }}
|
| 195 |
+
trivy:
|
| 196 |
+
name: Trivy
|
| 197 |
+
needs: build_image
|
| 198 |
+
runs-on: ubuntu-latest
|
| 199 |
+
environment:
|
| 200 |
+
name: container_health
|
| 201 |
+
steps:
|
| 202 |
+
- name: Checkout repository
|
| 203 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 204 |
+
- name: Run Trivy vulnerability scanner
|
| 205 |
+
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1
|
| 206 |
+
with:
|
| 207 |
+
image-ref: ${{ needs.build_image.outputs.image_tag }}
|
| 208 |
+
trivy-config: .github/lint/.trivy.yaml
|
| 209 |
+
format: sarif
|
| 210 |
+
output: trivy-results-image.sarif
|
| 211 |
+
exit-code: '1'
|
| 212 |
+
scanners: vuln,secret,misconfig,license
|
| 213 |
+
- name: Upload Trivy scan results to GitHub Security tab
|
| 214 |
+
if: success() || failure()
|
| 215 |
+
uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
|
| 216 |
+
with:
|
| 217 |
+
sarif_file: trivy-results-image.sarif
|
| 218 |
+
dockle:
|
| 219 |
+
name: Dockle
|
| 220 |
+
needs: build_image
|
| 221 |
+
runs-on: ubuntu-latest
|
| 222 |
+
environment:
|
| 223 |
+
name: container_health
|
| 224 |
+
steps:
|
| 225 |
+
- name: Lint the Container Image
|
| 226 |
+
uses: goodwithtech/dockle-action@e30e6af832aad6ea7dca2a248d31a85eab6dbd68 # v0.4.15
|
| 227 |
+
with:
|
| 228 |
+
image: ${{ needs.build_image.outputs.image_tag }}
|
| 229 |
+
format: sarif
|
| 230 |
+
output: dockle.sarif
|
| 231 |
+
accept-file: settings.py
|
| 232 |
+
accept-key: --chmod,--chown,GRADIO_SERVER_PORT,GRADIO_SERVER_NAME,FASTEMBED_CACHE_PATH,PATH
|
| 233 |
+
ignore: CIS-DI-0006
|
| 234 |
+
- name: upload Dockle scan SARIF report
|
| 235 |
+
if: success() || failure()
|
| 236 |
+
uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
|
| 237 |
+
with:
|
| 238 |
+
sarif_file: dockle.sarif
|
| 239 |
+
api_test:
|
| 240 |
+
name: API Test
|
| 241 |
+
needs: build_image
|
| 242 |
+
runs-on: ubuntu-latest
|
| 243 |
+
if: ${{ inputs.is_test }}
|
| 244 |
+
environment:
|
| 245 |
+
name: container_health
|
| 246 |
+
services:
|
| 247 |
+
vector_database:
|
| 248 |
+
image: qdrant/qdrant:latest@sha256:0425e3e03e7fd9b3dc95c4214546afe19de2eb2e28ca621441a56663ac6e1f46
|
| 249 |
+
ports:
|
| 250 |
+
- 6333:6333
|
| 251 |
+
app:
|
| 252 |
+
image: ${{ needs.build_image.outputs.image_tag }}
|
| 253 |
+
ports:
|
| 254 |
+
- 7860:7860
|
| 255 |
+
env:
|
| 256 |
+
MODEL__URL: https://api.groq.com/openai/v1
|
| 257 |
+
MODEL__API_KEY: ${{ secrets.GROQ_API_KEY }}
|
| 258 |
+
MODEL__NAME: llama3-70b-8192
|
| 259 |
+
VECTOR_DATABASE__URL: http://vector_database:6333
|
| 260 |
+
VECTOR_DATABASE__NAME: test
|
| 261 |
+
options: >-
|
| 262 |
+
--health-cmd "curl -o /dev/null -f -s -w 'Status: %{http_code}, Time: %{time_total}s'
|
| 263 |
+
http://localhost:7860/" --health-interval 10s --health-timeout
|
| 264 |
+
10s --health-start-period 20s --health-retries 15
|
| 265 |
+
steps:
|
| 266 |
+
- name: Echo URL
|
| 267 |
+
run: echo "${{ github.event.repository.name }} available on localhost:${{ job.services.app.ports['7860'] }}"
|
| 268 |
+
- name: Checkout repository
|
| 269 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 270 |
+
- name: Install uv
|
| 271 |
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
| 272 |
+
with:
|
| 273 |
+
enable-cache: true
|
| 274 |
+
activate-environment: true
|
| 275 |
+
- name: Install deps
|
| 276 |
+
run: uv sync --only-dev
|
| 277 |
+
- name: Test
|
| 278 |
+
uses: pavelzw/pytest-action@510c5e90c360a185039bea56ce8b3e7e51a16507 # v2.2.0
|
| 279 |
+
with:
|
| 280 |
+
click-to-expand: false
|
| 281 |
+
custom-arguments: tests/test_app.py::test_app -p no:warnings
|
| 282 |
+
env:
|
| 283 |
+
MERGIFY_TOKEN: ${{ secrets.MERGIFY_TOKEN }}
|
| 284 |
+
clean:
|
| 285 |
+
name: Cleaning GHCR
|
| 286 |
+
needs:
|
| 287 |
+
- api_test
|
| 288 |
+
- docker_scout
|
| 289 |
+
- dockle
|
| 290 |
+
- trivy
|
| 291 |
+
- grype
|
| 292 |
+
- syft
|
| 293 |
+
- trufflehog
|
| 294 |
+
if: ${{ inputs.registry == 'ghcr.io' && ( success() || failure() ) && !contains(github.event.head_commit.message, '[skip ghcr clean]') }}
|
| 295 |
+
runs-on: ubuntu-latest
|
| 296 |
+
environment:
|
| 297 |
+
name: docker_image
|
| 298 |
+
steps:
|
| 299 |
+
- name: GHCR Cleaning
|
| 300 |
+
uses: snok/container-retention-policy@3b0972b2276b171b212f8c4efbca59ebba26eceb # v3.0.1
|
| 301 |
+
with:
|
| 302 |
+
account: ${{ github.repository_owner }}
|
| 303 |
+
token: ${{ secrets.GH_TOKEN }}
|
| 304 |
+
image-names: ${{ github.event.repository.name }}
|
| 305 |
+
image-tags: '!latest !*.*.*'
|
| 306 |
+
cut-off: 1s
|
.github/workflows/.lint.yaml
ADDED
|
@@ -0,0 +1,363 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Lint
|
| 2 |
+
on:
|
| 3 |
+
workflow_call:
|
| 4 |
+
permissions:
|
| 5 |
+
contents: write
|
| 6 |
+
pull-requests: write
|
| 7 |
+
checks: write
|
| 8 |
+
security-events: write
|
| 9 |
+
actions: read
|
| 10 |
+
jobs:
|
| 11 |
+
taplo:
|
| 12 |
+
name: Taplo ${{ matrix.command }}
|
| 13 |
+
runs-on: ubuntu-latest
|
| 14 |
+
environment:
|
| 15 |
+
name: code_quality
|
| 16 |
+
strategy:
|
| 17 |
+
fail-fast: false
|
| 18 |
+
matrix:
|
| 19 |
+
command:
|
| 20 |
+
- format
|
| 21 |
+
- lint
|
| 22 |
+
steps:
|
| 23 |
+
- name: Checkout repository
|
| 24 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 25 |
+
- name: Install taplo
|
| 26 |
+
uses: baptiste0928/cargo-install@b687c656bda5733207e629b50a22bf68974a0305 # v3.3.2
|
| 27 |
+
with:
|
| 28 |
+
crate: taplo-cli
|
| 29 |
+
locked: true
|
| 30 |
+
- name: ${{ matrix.command }}
|
| 31 |
+
run: >-
|
| 32 |
+
taplo ${{matrix.command}}
|
| 33 |
+
--config .github/lint/.taplo.toml
|
| 34 |
+
${{matrix.command == 'lint' && '--default-schema-catalogs' || ''}}
|
| 35 |
+
- name: Commit and push applied formatter fixes
|
| 36 |
+
if: matrix.command == 'format'
|
| 37 |
+
uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
|
| 38 |
+
with:
|
| 39 |
+
commit_message: '[Taplo] Apply formatter fixes'
|
| 40 |
+
commit_options: --no-verify
|
| 41 |
+
trufflehog:
|
| 42 |
+
name: TruffleHog
|
| 43 |
+
runs-on: ubuntu-latest
|
| 44 |
+
environment:
|
| 45 |
+
name: code_quality
|
| 46 |
+
steps:
|
| 47 |
+
- name: Install trufflehog
|
| 48 |
+
uses: jaxxstorm/action-install-gh-release@6096f2a2bbfee498ced520b6922ac2c06e990ed2 # v2.1.0
|
| 49 |
+
with:
|
| 50 |
+
repo: trufflesecurity/trufflehog
|
| 51 |
+
cache: enable
|
| 52 |
+
- name: Git Secret Scanning
|
| 53 |
+
run: >-
|
| 54 |
+
trufflehog git ${{github.event.repository.html_url}} --branch=${{github.head_ref || github.ref_name}}
|
| 55 |
+
--fail --github-actions --results=verified,unknown --log-level=4 --no-update
|
| 56 |
+
pre-commit:
|
| 57 |
+
name: pre-commit
|
| 58 |
+
runs-on: ubuntu-latest
|
| 59 |
+
environment:
|
| 60 |
+
name: code_quality
|
| 61 |
+
steps:
|
| 62 |
+
- name: Checkout repository
|
| 63 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 64 |
+
- name: Install uv
|
| 65 |
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
| 66 |
+
with:
|
| 67 |
+
enable-cache: true
|
| 68 |
+
activate-environment: true
|
| 69 |
+
- name: Restore pre-commit cache
|
| 70 |
+
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
| 71 |
+
id: cache-restore
|
| 72 |
+
with:
|
| 73 |
+
path: ~/.cache/pre-commit
|
| 74 |
+
key: pre-commit-${{ hashFiles('**/.pre-commit-config.yaml') }}
|
| 75 |
+
restore-keys: pre-commit-
|
| 76 |
+
- name: Run pre-commit hooks
|
| 77 |
+
run: uvx pre-commit run --show-diff-on-failure --color=always --all-files
|
| 78 |
+
- name: Save pre-commit cache
|
| 79 |
+
uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
| 80 |
+
if: always() && steps.cache-restore.outputs.cache-hit != 'true'
|
| 81 |
+
with:
|
| 82 |
+
path: ~/.cache/pre-commit
|
| 83 |
+
key: ${{ steps.cache-restore.outputs.cache-primary-key }}
|
| 84 |
+
- name: Run pre-commit-ci-lite
|
| 85 |
+
uses: pre-commit-ci/lite-action@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 # v1.1.0
|
| 86 |
+
if: always()
|
| 87 |
+
uv_lock:
|
| 88 |
+
name: UV Lock Check
|
| 89 |
+
runs-on: ubuntu-latest
|
| 90 |
+
environment:
|
| 91 |
+
name: code_quality
|
| 92 |
+
steps:
|
| 93 |
+
- name: Checkout repository
|
| 94 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 95 |
+
- name: Install uv
|
| 96 |
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
| 97 |
+
with:
|
| 98 |
+
enable-cache: true
|
| 99 |
+
activate-environment: true
|
| 100 |
+
- name: Check if the lockfile is up-to-date
|
| 101 |
+
id: uv_lock_check
|
| 102 |
+
run: uv lock --check
|
| 103 |
+
- name: Job Summary
|
| 104 |
+
uses: jazanne/job-summary-action@690eb386a0b86fe4da7c6f0e543e61330ff09f06 # v1.0.0
|
| 105 |
+
if: success() || failure()
|
| 106 |
+
with:
|
| 107 |
+
summary: |
|
| 108 |
+
## UV Lock Check
|
| 109 |
+
- **Status**: ${{ steps.uv_lock_check.outcome == 'success' && ':white_check_mark:' || ':x:' }}
|
| 110 |
+
ls_lint:
|
| 111 |
+
name: ls-lint
|
| 112 |
+
runs-on: ubuntu-latest
|
| 113 |
+
environment:
|
| 114 |
+
name: code_quality
|
| 115 |
+
steps:
|
| 116 |
+
- name: Checkout repository
|
| 117 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 118 |
+
- name: Lint file names
|
| 119 |
+
uses: ls-lint/action@02e380fe8733d499cbfc9e22276de5085508a5bd # v2.3.1
|
| 120 |
+
with:
|
| 121 |
+
config: .github/lint/.ls-lint.yaml
|
| 122 |
+
ruff:
|
| 123 |
+
name: Ruff ${{ matrix.command }}
|
| 124 |
+
runs-on: ubuntu-latest
|
| 125 |
+
environment:
|
| 126 |
+
name: code_quality
|
| 127 |
+
strategy:
|
| 128 |
+
fail-fast: false
|
| 129 |
+
matrix:
|
| 130 |
+
command:
|
| 131 |
+
- check
|
| 132 |
+
- format
|
| 133 |
+
include:
|
| 134 |
+
- command: check
|
| 135 |
+
output: sarif
|
| 136 |
+
- command: format
|
| 137 |
+
output: github
|
| 138 |
+
steps:
|
| 139 |
+
- name: Checkout repository
|
| 140 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 141 |
+
with:
|
| 142 |
+
token: ${{ secrets.GH_TOKEN }}
|
| 143 |
+
- name: ${{ matrix.command }}
|
| 144 |
+
uses: astral-sh/ruff-action@57714a7c8a2e59f32539362ba31877a1957dded1 # v3.5.1
|
| 145 |
+
with:
|
| 146 |
+
args: >-
|
| 147 |
+
${{ matrix.command }} --config .github/lint/.ruff.toml
|
| 148 |
+
--output-format ${{matrix.output}}
|
| 149 |
+
${{matrix.output == 'sarif' && '--output-file ruff.sarif' || ''}}
|
| 150 |
+
- name: upload Ruff scan SARIF report
|
| 151 |
+
if: matrix.output == 'sarif' && ( success() || failure() )
|
| 152 |
+
uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
|
| 153 |
+
with:
|
| 154 |
+
sarif_file: ruff.sarif
|
| 155 |
+
- name: Commit and push applied Ruff fixes
|
| 156 |
+
if: matrix.output == 'github'
|
| 157 |
+
uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
|
| 158 |
+
with:
|
| 159 |
+
commit_message: '[Ruff] Apply format fixes'
|
| 160 |
+
commit_options: --no-verify
|
| 161 |
+
yamlfix:
|
| 162 |
+
name: YamlFix
|
| 163 |
+
runs-on: ubuntu-latest
|
| 164 |
+
environment:
|
| 165 |
+
name: code_quality
|
| 166 |
+
steps:
|
| 167 |
+
- name: Checkout repository
|
| 168 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 169 |
+
with:
|
| 170 |
+
token: ${{ secrets.GH_TOKEN }}
|
| 171 |
+
- name: Install uv
|
| 172 |
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
| 173 |
+
with:
|
| 174 |
+
enable-cache: true
|
| 175 |
+
activate-environment: true
|
| 176 |
+
- name: Format
|
| 177 |
+
run: uvx yamlfix . --config-file .github/lint/.yamlfix.toml
|
| 178 |
+
- name: Commit and push applied linter fixes
|
| 179 |
+
uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
|
| 180 |
+
with:
|
| 181 |
+
commit_message: '[YamlFix] Apply linters fixes'
|
| 182 |
+
commit_options: --no-verify
|
| 183 |
+
yamllint:
|
| 184 |
+
name: YamlLint
|
| 185 |
+
runs-on: ubuntu-latest
|
| 186 |
+
environment:
|
| 187 |
+
name: code_quality
|
| 188 |
+
steps:
|
| 189 |
+
- name: Checkout repository
|
| 190 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 191 |
+
- name: Install uv
|
| 192 |
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
| 193 |
+
with:
|
| 194 |
+
enable-cache: true
|
| 195 |
+
activate-environment: true
|
| 196 |
+
- name: Check
|
| 197 |
+
run: uvx yamllint . --strict -c=.github/lint/.yamllint.yaml --format github
|
| 198 |
+
syft:
|
| 199 |
+
name: Syft
|
| 200 |
+
runs-on: ubuntu-latest
|
| 201 |
+
environment:
|
| 202 |
+
name: code_quality
|
| 203 |
+
steps:
|
| 204 |
+
- name: Checkout repository
|
| 205 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 206 |
+
- name: SBOM Generation
|
| 207 |
+
uses: anchore/sbom-action@deef08a0db64bfad603422135db61477b16cef56 # v0.22.1
|
| 208 |
+
with:
|
| 209 |
+
path: .
|
| 210 |
+
dependency-snapshot: true
|
| 211 |
+
output-file: ${{ github.event.repository.name }}-sbom.json
|
| 212 |
+
format: syft-json
|
| 213 |
+
grype:
|
| 214 |
+
name: Grype
|
| 215 |
+
runs-on: ubuntu-latest
|
| 216 |
+
environment:
|
| 217 |
+
name: code_quality
|
| 218 |
+
steps:
|
| 219 |
+
- name: Checkout repository
|
| 220 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 221 |
+
- name: Scan current project
|
| 222 |
+
uses: anchore/scan-action@8d2fce09422cd6037e577f4130e9b925e9a37175 # v7.3.1
|
| 223 |
+
id: scan
|
| 224 |
+
with:
|
| 225 |
+
path: .
|
| 226 |
+
cache-db: true
|
| 227 |
+
- name: upload Anchore scan SARIF report
|
| 228 |
+
if: success() || failure()
|
| 229 |
+
uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
|
| 230 |
+
with:
|
| 231 |
+
sarif_file: ${{ steps.scan.outputs.sarif }}
|
| 232 |
+
trivy:
|
| 233 |
+
name: Trivy ${{ matrix.name }}
|
| 234 |
+
runs-on: ubuntu-latest
|
| 235 |
+
environment:
|
| 236 |
+
name: code_quality
|
| 237 |
+
strategy:
|
| 238 |
+
fail-fast: false
|
| 239 |
+
matrix:
|
| 240 |
+
scan-type:
|
| 241 |
+
- repo
|
| 242 |
+
- config
|
| 243 |
+
- fs
|
| 244 |
+
include:
|
| 245 |
+
- scan-type: repo
|
| 246 |
+
format: sarif
|
| 247 |
+
output: trivy-results-repo.sarif
|
| 248 |
+
name: Repo
|
| 249 |
+
- scan-type: config
|
| 250 |
+
format: sarif
|
| 251 |
+
output: trivy-results-config.sarif
|
| 252 |
+
name: IaC
|
| 253 |
+
- scan-type: fs
|
| 254 |
+
format: github
|
| 255 |
+
output: dependency-results.sbom.json
|
| 256 |
+
name: SBOM
|
| 257 |
+
steps:
|
| 258 |
+
- name: Checkout repository
|
| 259 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 260 |
+
- name: Run Trivy vulnerability scanner in repo mode
|
| 261 |
+
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1
|
| 262 |
+
with:
|
| 263 |
+
scan-type: ${{ matrix.scan-type }}
|
| 264 |
+
trivy-config: .github/lint/.trivy.yaml
|
| 265 |
+
format: ${{ matrix.format }}
|
| 266 |
+
output: ${{ matrix.output }}
|
| 267 |
+
github-pat: ${{ secrets.GH_TOKEN }}
|
| 268 |
+
exit-code: '1'
|
| 269 |
+
scanners: vuln,secret,misconfig
|
| 270 |
+
- name: Upload Trivy scan results to GitHub Security tab
|
| 271 |
+
if: matrix.scan-type != 'fs' && ( success() || failure() )
|
| 272 |
+
uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
|
| 273 |
+
with:
|
| 274 |
+
sarif_file: ${{ matrix.output }}
|
| 275 |
+
category: ${{ matrix.scan-type }}
|
| 276 |
+
- name: Upload trivy report as a Github artifact
|
| 277 |
+
if: matrix.scan-type == 'fs' && ( success() || failure() )
|
| 278 |
+
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
| 279 |
+
with:
|
| 280 |
+
name: trivy-sbom-report
|
| 281 |
+
path: ${{ matrix.output }}
|
| 282 |
+
dclint:
|
| 283 |
+
name: DCLint
|
| 284 |
+
runs-on: ubuntu-latest
|
| 285 |
+
environment:
|
| 286 |
+
name: code_quality
|
| 287 |
+
steps:
|
| 288 |
+
- name: Checkout repository
|
| 289 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 290 |
+
- name: Lint Docker Compose file
|
| 291 |
+
uses: docker-compose-linter/dclint-github-action@18659f6a7956706cb67cf9c1ad5e55f4352cbc17 # v1.6.0
|
| 292 |
+
with:
|
| 293 |
+
fix: true
|
| 294 |
+
recursive: true
|
| 295 |
+
ty:
|
| 296 |
+
name: Ty
|
| 297 |
+
runs-on: ubuntu-latest
|
| 298 |
+
environment:
|
| 299 |
+
name: code_quality
|
| 300 |
+
steps:
|
| 301 |
+
- name: Checkout repository
|
| 302 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 303 |
+
- name: Install uv
|
| 304 |
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
| 305 |
+
with:
|
| 306 |
+
enable-cache: true
|
| 307 |
+
activate-environment: true
|
| 308 |
+
- name: Check
|
| 309 |
+
run: uvx ty check --output-format github
|
| 310 |
+
markdownlint:
|
| 311 |
+
name: MarkdownLint
|
| 312 |
+
runs-on: ubuntu-latest
|
| 313 |
+
environment:
|
| 314 |
+
name: code_quality
|
| 315 |
+
steps:
|
| 316 |
+
- name: Checkout repository
|
| 317 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 318 |
+
- name: Lint Markdown files
|
| 319 |
+
uses: DavidAnson/markdownlint-cli2-action@07035fd053f7be764496c0f8d8f9f41f98305101 # v22.0.0
|
| 320 |
+
with:
|
| 321 |
+
globs: '**/*.md'
|
| 322 |
+
config: .github/lint/.markdownlint.yaml
|
| 323 |
+
fix: true
|
| 324 |
+
hadolint:
|
| 325 |
+
name: Hadolint
|
| 326 |
+
runs-on: ubuntu-latest
|
| 327 |
+
environment:
|
| 328 |
+
name: code_quality
|
| 329 |
+
steps:
|
| 330 |
+
- name: Checkout repository
|
| 331 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 332 |
+
- name: Lint Dockerfile
|
| 333 |
+
uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0
|
| 334 |
+
with:
|
| 335 |
+
config: .github/lint/.hadolint.yaml
|
| 336 |
+
format: sarif
|
| 337 |
+
output-file: hadolint.sarif
|
| 338 |
+
- name: upload Hadolint scan SARIF report
|
| 339 |
+
if: success() || failure()
|
| 340 |
+
uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
|
| 341 |
+
with:
|
| 342 |
+
sarif_file: hadolint.sarif
|
| 343 |
+
actionlint:
|
| 344 |
+
name: ActionLint
|
| 345 |
+
runs-on: ubuntu-latest
|
| 346 |
+
environment:
|
| 347 |
+
name: code_quality
|
| 348 |
+
steps:
|
| 349 |
+
- name: Checkout repository
|
| 350 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 351 |
+
- name: Install actionlint
|
| 352 |
+
uses: jaxxstorm/action-install-gh-release@6096f2a2bbfee498ced520b6922ac2c06e990ed2 # v2.1.0
|
| 353 |
+
with:
|
| 354 |
+
repo: rhysd/actionlint
|
| 355 |
+
cache: enable
|
| 356 |
+
- name: Download actionlint-matcher.json
|
| 357 |
+
run: >-
|
| 358 |
+
curl -fsSL https://raw.githubusercontent.com/rhysd/actionlint/main/.github/actionlint-matcher.json
|
| 359 |
+
-o .github/actionlint-matcher.json
|
| 360 |
+
- name: Run actionlint
|
| 361 |
+
run: |-
|
| 362 |
+
echo "::add-matcher::.github/actionlint-matcher.json"
|
| 363 |
+
actionlint -color
|
.github/workflows/build.yaml
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Build
|
| 2 |
+
on:
|
| 3 |
+
push:
|
| 4 |
+
tags:
|
| 5 |
+
- '[0-9]+.[0-9]+.[0-9]+'
|
| 6 |
+
- '[0-9]+.[0-9]+.[0-9]+a[0-9]+'
|
| 7 |
+
- '[0-9]+.[0-9]+.[0-9]+b[0-9]+'
|
| 8 |
+
permissions: read-all
|
| 9 |
+
concurrency:
|
| 10 |
+
group: ${{ github.workflow }}-${{ github.ref_name }}
|
| 11 |
+
cancel-in-progress: true
|
| 12 |
+
jobs:
|
| 13 |
+
setup_and_build:
|
| 14 |
+
name: Setup and Build
|
| 15 |
+
environment:
|
| 16 |
+
name: uv
|
| 17 |
+
url: ${{github.event.repository.html_url}}/commits/${{github.ref_name}}
|
| 18 |
+
env:
|
| 19 |
+
UV_COMPILE_BYTECODE: '1'
|
| 20 |
+
UV_LINK_MODE: copy
|
| 21 |
+
permissions:
|
| 22 |
+
contents: write
|
| 23 |
+
runs-on: ubuntu-latest
|
| 24 |
+
steps:
|
| 25 |
+
- name: Checkout repository
|
| 26 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 27 |
+
with:
|
| 28 |
+
token: ${{ secrets.GH_TOKEN }}
|
| 29 |
+
- name: Get Package version from pyproject.toml
|
| 30 |
+
id: get_package_version
|
| 31 |
+
uses: mikefarah/yq@065b200af9851db0d5132f50bc10b1406ea5c0a8 # v4.50.1
|
| 32 |
+
with:
|
| 33 |
+
cmd: yq -roy '.project.version' pyproject.toml
|
| 34 |
+
- name: Install uv
|
| 35 |
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
| 36 |
+
with:
|
| 37 |
+
enable-cache: true
|
| 38 |
+
activate-environment: true
|
| 39 |
+
- name: Install the project
|
| 40 |
+
run: uv sync --no-dev --frozen --no-editable
|
| 41 |
+
- name: Update Project Version
|
| 42 |
+
if: ${{ github.ref_name != steps.get_package_version.outputs.result }}
|
| 43 |
+
run: uv version ${{ github.ref_name }}
|
| 44 |
+
- name: Build source and wheel distribution
|
| 45 |
+
run: uv build
|
| 46 |
+
- name: Upload artifacts
|
| 47 |
+
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
| 48 |
+
with:
|
| 49 |
+
name: dist
|
| 50 |
+
path: dist/
|
| 51 |
+
- name: Update the main branch to the updated version
|
| 52 |
+
if: ${{ github.ref_name != steps.get_package_version.outputs.result }}
|
| 53 |
+
uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
|
| 54 |
+
with:
|
| 55 |
+
commit_message: 'Version: ${{ github.ref_name }}'
|
| 56 |
+
branch: main
|
| 57 |
+
commit_options: --no-verify
|
| 58 |
+
- name: Update the tag to the updated version
|
| 59 |
+
if: ${{ github.ref_name != steps.get_package_version.outputs.result }}
|
| 60 |
+
run: |
|
| 61 |
+
git tag --force ${{ github.ref_name }}
|
| 62 |
+
git push origin --force HEAD:refs/tags/${{ github.ref_name }}
|
| 63 |
+
github_release:
|
| 64 |
+
name: Create GitHub Release
|
| 65 |
+
needs: setup_and_build
|
| 66 |
+
runs-on: ubuntu-latest
|
| 67 |
+
environment:
|
| 68 |
+
name: github
|
| 69 |
+
url: ${{github.event.repository.html_url}}/releases/tag/${{github.ref_name}}
|
| 70 |
+
permissions:
|
| 71 |
+
contents: write
|
| 72 |
+
steps:
|
| 73 |
+
- name: Checkout repository
|
| 74 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 75 |
+
- name: Download artifacts
|
| 76 |
+
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
| 77 |
+
with:
|
| 78 |
+
name: dist
|
| 79 |
+
path: dist/
|
| 80 |
+
- name: Create GitHub Release
|
| 81 |
+
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
|
| 82 |
+
with:
|
| 83 |
+
files: dist/*
|
| 84 |
+
generate_release_notes: true
|
| 85 |
+
make_latest: true
|
| 86 |
+
fail_on_unmatched_files: true
|
.github/workflows/ci_tools.yaml
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: CI Tools
|
| 2 |
+
on:
|
| 3 |
+
push:
|
| 4 |
+
branches:
|
| 5 |
+
- main
|
| 6 |
+
issue_comment:
|
| 7 |
+
types:
|
| 8 |
+
- created
|
| 9 |
+
- edited
|
| 10 |
+
workflow_dispatch:
|
| 11 |
+
permissions:
|
| 12 |
+
id-token: write
|
| 13 |
+
contents: write
|
| 14 |
+
pull-requests: read
|
| 15 |
+
issues: read
|
| 16 |
+
jobs:
|
| 17 |
+
opencode:
|
| 18 |
+
if: |
|
| 19 |
+
github.event_name == 'issue_comment' &&
|
| 20 |
+
(
|
| 21 |
+
contains(github.event.comment.body, ' /oc') ||
|
| 22 |
+
startsWith(github.event.comment.body, '/oc') ||
|
| 23 |
+
contains(github.event.comment.body, ' /opencode') ||
|
| 24 |
+
startsWith(github.event.comment.body, '/opencode')
|
| 25 |
+
)
|
| 26 |
+
name: Opencode
|
| 27 |
+
runs-on: ubuntu-latest
|
| 28 |
+
environment:
|
| 29 |
+
name: ai_agent
|
| 30 |
+
steps:
|
| 31 |
+
- name: Checkout repository
|
| 32 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 33 |
+
- name: Run opencode
|
| 34 |
+
uses: sst/opencode/github@8f537940178772deedf3317c5c669950f1f6c5a6 # v1.1.45
|
| 35 |
+
env:
|
| 36 |
+
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
|
| 37 |
+
with:
|
| 38 |
+
model: opencode/grok-code
|
| 39 |
+
uv_lock_sync:
|
| 40 |
+
if: |
|
| 41 |
+
github.event_name == 'workflow_dispatch' ||
|
| 42 |
+
(
|
| 43 |
+
github.event_name == 'issue_comment' &&
|
| 44 |
+
(
|
| 45 |
+
contains(github.event.comment.body, ' /uv-lock-sync') ||
|
| 46 |
+
startsWith(github.event.comment.body, '/uv-lock-sync')
|
| 47 |
+
)
|
| 48 |
+
)
|
| 49 |
+
name: UV Lock Sync
|
| 50 |
+
runs-on: ubuntu-latest
|
| 51 |
+
environment:
|
| 52 |
+
name: lockfile
|
| 53 |
+
steps:
|
| 54 |
+
- name: Checkout repository
|
| 55 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 56 |
+
with:
|
| 57 |
+
token: ${{ secrets.GH_TOKEN }}
|
| 58 |
+
- name: Install uv
|
| 59 |
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
| 60 |
+
with:
|
| 61 |
+
enable-cache: true
|
| 62 |
+
activate-environment: true
|
| 63 |
+
- name: Sync dependencies and uv.lock
|
| 64 |
+
run: uv lock
|
| 65 |
+
- name: Commit and push changes
|
| 66 |
+
uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
|
| 67 |
+
with:
|
| 68 |
+
commit_message: Sync uv.lock
|
| 69 |
+
commit_options: --no-verify
|
| 70 |
+
huggingface:
|
| 71 |
+
name: Sync HuggingFace Space
|
| 72 |
+
runs-on: ubuntu-latest
|
| 73 |
+
if: |
|
| 74 |
+
github.event_name == 'push' ||
|
| 75 |
+
github.event_name == 'workflow_dispatch' ||
|
| 76 |
+
(
|
| 77 |
+
github.event_name == 'issue_comment' &&
|
| 78 |
+
(
|
| 79 |
+
contains(github.event.comment.body, ' /hf-sync') ||
|
| 80 |
+
startsWith(github.event.comment.body, '/hf-sync')
|
| 81 |
+
)
|
| 82 |
+
)
|
| 83 |
+
permissions:
|
| 84 |
+
contents: read
|
| 85 |
+
id-token: write
|
| 86 |
+
environment:
|
| 87 |
+
name: huggingface
|
| 88 |
+
url: https://huggingface.co/spaces/${{github.repository}}
|
| 89 |
+
steps:
|
| 90 |
+
- name: Checkout repository
|
| 91 |
+
uses: actions/checkout@v4.0.0
|
| 92 |
+
with:
|
| 93 |
+
fetch-depth: 0
|
| 94 |
+
lfs: true
|
| 95 |
+
- name: Install uv
|
| 96 |
+
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
| 97 |
+
with:
|
| 98 |
+
enable-cache: true
|
| 99 |
+
activate-environment: true
|
| 100 |
+
- name: Push to HF
|
| 101 |
+
env:
|
| 102 |
+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
| 103 |
+
COMMIT_MESSAGE: ${{ github.event.head_commit.message || 'Sync from GitHub' }}
|
| 104 |
+
run: >-
|
| 105 |
+
uvx hf upload ${{github.repository}} . . --repo-type space
|
| 106 |
+
--delete '*' --exclude '.github' --commit-message "$COMMIT_MESSAGE"
|
.github/workflows/release.yaml
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Release
|
| 2 |
+
on:
|
| 3 |
+
release:
|
| 4 |
+
types:
|
| 5 |
+
- published
|
| 6 |
+
permissions: read-all
|
| 7 |
+
concurrency:
|
| 8 |
+
group: ${{ github.workflow }}-${{ github.ref_name }}
|
| 9 |
+
cancel-in-progress: true
|
| 10 |
+
jobs:
|
| 11 |
+
pypi:
|
| 12 |
+
name: Upload Python Package
|
| 13 |
+
runs-on: ubuntu-latest
|
| 14 |
+
permissions:
|
| 15 |
+
contents: read
|
| 16 |
+
id-token: write
|
| 17 |
+
environment:
|
| 18 |
+
name: pypi
|
| 19 |
+
url: https://pypi.org/project/${{github.event.repository.name}}/${{github.event.release.tag_name}}
|
| 20 |
+
steps:
|
| 21 |
+
- name: Retrieve release distributions
|
| 22 |
+
uses: robinraju/release-downloader@daf26c55d821e836577a15f77d86ddc078948b05 # v1.12
|
| 23 |
+
with:
|
| 24 |
+
tag: ${{ github.event.release.tag_name }}
|
| 25 |
+
out-file-path: dist/
|
| 26 |
+
fileName: '*'
|
| 27 |
+
- name: Publish release distributions to PyPI
|
| 28 |
+
uses: pypa/gh-action-pypi-publish@release/v1
|
| 29 |
+
with:
|
| 30 |
+
packages-dir: dist/
|
| 31 |
+
huggingface:
|
| 32 |
+
name: Tag HuggingFace Space
|
| 33 |
+
runs-on: ubuntu-latest
|
| 34 |
+
permissions:
|
| 35 |
+
contents: read
|
| 36 |
+
id-token: write
|
| 37 |
+
environment:
|
| 38 |
+
name: huggingface
|
| 39 |
+
url: https://huggingface.co/spaces/${{github.repository}}/tree/${{github.event.release.tag_name}}
|
| 40 |
+
steps:
|
| 41 |
+
- name: Install uv
|
| 42 |
+
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0
|
| 43 |
+
with:
|
| 44 |
+
enable-cache: true
|
| 45 |
+
activate-environment: true
|
| 46 |
+
- name: Push to HF
|
| 47 |
+
env:
|
| 48 |
+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
| 49 |
+
run: >-
|
| 50 |
+
uvx hf repo tag create ${{github.repository}} ${{github.event.release.tag_name}}
|
| 51 |
+
--repo-type space
|
| 52 |
+
image:
|
| 53 |
+
name: Release Image
|
| 54 |
+
needs: pypi
|
| 55 |
+
permissions:
|
| 56 |
+
contents: read
|
| 57 |
+
packages: write
|
| 58 |
+
attestations: write
|
| 59 |
+
id-token: write
|
| 60 |
+
strategy:
|
| 61 |
+
matrix:
|
| 62 |
+
registry:
|
| 63 |
+
- ghcr.io
|
| 64 |
+
- docker.io
|
| 65 |
+
uses: ./.github/workflows/.docker.yaml
|
| 66 |
+
with:
|
| 67 |
+
is_test: false
|
| 68 |
+
registry: ${{ matrix.registry }}
|
| 69 |
+
install_source: ${{github.event.repository.name}}==${{github.event.release.tag_name}}
|
| 70 |
+
secrets: inherit
|
.github/workflows/test.yaml
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Test
|
| 2 |
+
on:
|
| 3 |
+
push:
|
| 4 |
+
branches:
|
| 5 |
+
- main
|
| 6 |
+
pull_request:
|
| 7 |
+
workflow_dispatch:
|
| 8 |
+
concurrency:
|
| 9 |
+
group: ${{ github.workflow }}-${{ github.ref_name }}
|
| 10 |
+
cancel-in-progress: true
|
| 11 |
+
permissions: read-all
|
| 12 |
+
jobs:
|
| 13 |
+
compatibility:
|
| 14 |
+
name: Check Dependency Compatibility
|
| 15 |
+
runs-on: ubuntu-latest
|
| 16 |
+
environment:
|
| 17 |
+
name: code_quality
|
| 18 |
+
permissions:
|
| 19 |
+
checks: write
|
| 20 |
+
contents: read
|
| 21 |
+
steps:
|
| 22 |
+
- name: Checkout repository
|
| 23 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 24 |
+
- name: Install uv
|
| 25 |
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
| 26 |
+
with:
|
| 27 |
+
enable-cache: true
|
| 28 |
+
activate-environment: true
|
| 29 |
+
- name: Install the project
|
| 30 |
+
id: dependency_check
|
| 31 |
+
run: uv sync --frozen --no-install-project
|
| 32 |
+
- name: Job Summary
|
| 33 |
+
uses: jazanne/job-summary-action@690eb386a0b86fe4da7c6f0e543e61330ff09f06 # v1.0.0
|
| 34 |
+
if: success() || failure()
|
| 35 |
+
with:
|
| 36 |
+
summary: |-
|
| 37 |
+
## Dependency Compatibility Check
|
| 38 |
+
- **Status**: ${{ steps.dependency_check.outcome == 'success' && ':white_check_mark:' || ':x:' }}
|
| 39 |
+
- name: Show Dependency Tree
|
| 40 |
+
if: steps.dependency_check.outcome == 'success'
|
| 41 |
+
run: |
|
| 42 |
+
echo "## Dependency Tree" >> $GITHUB_STEP_SUMMARY
|
| 43 |
+
echo "<details>" >> $GITHUB_STEP_SUMMARY
|
| 44 |
+
echo "<summary> Dependency Tree </summary>" >> $GITHUB_STEP_SUMMARY
|
| 45 |
+
echo "" >> $GITHUB_STEP_SUMMARY
|
| 46 |
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
| 47 |
+
echo "$(uv tree --show-sizes)" >> $GITHUB_STEP_SUMMARY
|
| 48 |
+
echo '```' >> $GITHUB_STEP_SUMMARY
|
| 49 |
+
echo "</details>" >> $GITHUB_STEP_SUMMARY
|
| 50 |
+
lint:
|
| 51 |
+
name: Lint
|
| 52 |
+
permissions:
|
| 53 |
+
contents: write
|
| 54 |
+
pull-requests: write
|
| 55 |
+
checks: write
|
| 56 |
+
security-events: write
|
| 57 |
+
actions: read
|
| 58 |
+
needs: compatibility
|
| 59 |
+
uses: ./.github/workflows/.lint.yaml
|
| 60 |
+
secrets: inherit
|
| 61 |
+
image:
|
| 62 |
+
name: Test Image
|
| 63 |
+
permissions:
|
| 64 |
+
contents: write
|
| 65 |
+
packages: write
|
| 66 |
+
attestations: write
|
| 67 |
+
id-token: write
|
| 68 |
+
security-events: write
|
| 69 |
+
actions: read
|
| 70 |
+
needs: compatibility
|
| 71 |
+
uses: ./.github/workflows/.docker.yaml
|
| 72 |
+
with:
|
| 73 |
+
is_test: true
|
| 74 |
+
registry: ghcr.io
|
| 75 |
+
install_source: git+${{ github.event.repository.html_url }}@${{ github.sha }}
|
| 76 |
+
secrets: inherit
|
.github/workflows/version.yaml
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Version
|
| 2 |
+
on:
|
| 3 |
+
push:
|
| 4 |
+
branches:
|
| 5 |
+
- main
|
| 6 |
+
paths:
|
| 7 |
+
- pyproject.toml
|
| 8 |
+
- uv.lock
|
| 9 |
+
- Dockerfile
|
| 10 |
+
concurrency:
|
| 11 |
+
group: ${{ github.workflow }}-${{ github.ref_name }}
|
| 12 |
+
cancel-in-progress: false
|
| 13 |
+
permissions: read-all
|
| 14 |
+
jobs:
|
| 15 |
+
version:
|
| 16 |
+
name: Versioning
|
| 17 |
+
runs-on: ubuntu-latest
|
| 18 |
+
if: github.actor == 'renovate[bot]' || github.actor == 'mergify[bot]'
|
| 19 |
+
permissions:
|
| 20 |
+
contents: write
|
| 21 |
+
environment:
|
| 22 |
+
name: versioning
|
| 23 |
+
steps:
|
| 24 |
+
- name: Checkout repository
|
| 25 |
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
| 26 |
+
with:
|
| 27 |
+
token: ${{ secrets.GH_TOKEN }}
|
| 28 |
+
fetch-depth: 0
|
| 29 |
+
- name: Install uv
|
| 30 |
+
uses: astral-sh/setup-uv@803947b9bd8e9f986429fa0c5a41c367cd732b41 # v7.2.1
|
| 31 |
+
with:
|
| 32 |
+
enable-cache: true
|
| 33 |
+
activate-environment: true
|
| 34 |
+
- name: Increase the patch version
|
| 35 |
+
run: uv version --bump patch
|
| 36 |
+
- name: Get Package version from pyproject.toml
|
| 37 |
+
id: get_package_version
|
| 38 |
+
uses: mikefarah/yq@065b200af9851db0d5132f50bc10b1406ea5c0a8 # v4.50.1
|
| 39 |
+
with:
|
| 40 |
+
cmd: yq -roy '.project.version' pyproject.toml
|
| 41 |
+
- name: Commit updated count
|
| 42 |
+
uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
|
| 43 |
+
with:
|
| 44 |
+
commit_message: 'Tag: ${{ steps.get_package_version.outputs.result }}'
|
| 45 |
+
tagging_message: ${{ steps.get_package_version.outputs.result }}
|
.gitignore
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
**/__pycache__/
|
| 2 |
+
.env
|
| 3 |
+
.mypy_cache/
|
| 4 |
+
.ruff_cache/
|
| 5 |
+
.venv/
|
| 6 |
+
logs/
|
| 7 |
+
results/
|
| 8 |
+
qdrant_storage/
|
| 9 |
+
assets/audio/
|
| 10 |
+
assets/video/
|
| 11 |
+
agno/
|
| 12 |
+
.vscode/settings.json
|
.idea/.gitignore
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Default ignored files
|
| 2 |
+
/shelf/
|
| 3 |
+
/workspace.xml
|
| 4 |
+
# Ignored default folder with query files
|
| 5 |
+
/queries/
|
| 6 |
+
# Datasource local storage ignored files
|
| 7 |
+
/dataSources/
|
| 8 |
+
/dataSources.local.xml
|
| 9 |
+
# Editor-based HTTP Client requests
|
| 10 |
+
/httpRequests/
|
| 11 |
+
|
| 12 |
+
copilot.*.xml
|
.idea/chattr.iml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
+
<module type="PYTHON_MODULE" version="4">
|
| 3 |
+
<component name="NewModuleRootManager">
|
| 4 |
+
<content url="file://$MODULE_DIR$">
|
| 5 |
+
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
| 6 |
+
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
| 7 |
+
</content>
|
| 8 |
+
<orderEntry type="jdk" jdkName="uv (chattr)" jdkType="Python SDK" />
|
| 9 |
+
<orderEntry type="sourceFolder" forTests="false" />
|
| 10 |
+
</component>
|
| 11 |
+
<component name="PyDocumentationSettings">
|
| 12 |
+
<option name="format" value="GOOGLE" />
|
| 13 |
+
<option name="myDocStringFormat" value="Google" />
|
| 14 |
+
</component>
|
| 15 |
+
</module>
|
.idea/inspectionProfiles/Project_Default.xml
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<component name="InspectionProjectProfileManager">
|
| 2 |
+
<profile version="1.0">
|
| 3 |
+
<option name="myName" value="Project Default" />
|
| 4 |
+
<inspection_tool class="AlphaUnsortedPropertiesFile" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
| 5 |
+
<inspection_tool class="AngularAmbiguousComponentTag" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 6 |
+
<inspection_tool class="AngularBindingTypeMismatch" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 7 |
+
<inspection_tool class="AngularCliAddDependency" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 8 |
+
<inspection_tool class="AngularDeferBlockOnTrigger" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 9 |
+
<inspection_tool class="AngularForBlockNonIterableVar" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 10 |
+
<inspection_tool class="AngularIllegalForLoopTrackAccess" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 11 |
+
<inspection_tool class="AngularInaccessibleSymbol" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 12 |
+
<inspection_tool class="AngularIncorrectBlockUsage" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 13 |
+
<inspection_tool class="AngularIncorrectLetUsage" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 14 |
+
<inspection_tool class="AngularIncorrectTemplateDefinition" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 15 |
+
<inspection_tool class="AngularInsecureBindingToEvent" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 16 |
+
<inspection_tool class="AngularInvalidAnimationTriggerAssignment" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 17 |
+
<inspection_tool class="AngularInvalidEntryComponent" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 18 |
+
<inspection_tool class="AngularInvalidI18nAttribute" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 19 |
+
<inspection_tool class="AngularInvalidImportedOrDeclaredSymbol" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 20 |
+
<inspection_tool class="AngularInvalidSelector" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 21 |
+
<inspection_tool class="AngularInvalidTemplateReferenceVariable" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 22 |
+
<inspection_tool class="AngularMissingEventHandler" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 23 |
+
<inspection_tool class="AngularMissingOrInvalidDeclarationInModule" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 24 |
+
<inspection_tool class="AngularMissingRequiredDirectiveInputBinding" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 25 |
+
<inspection_tool class="AngularMultipleStructuralDirectives" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 26 |
+
<inspection_tool class="AngularNgOptimizedImage" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 27 |
+
<inspection_tool class="AngularNonEmptyNgContent" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 28 |
+
<inspection_tool class="AngularNonStandaloneComponentImports" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 29 |
+
<inspection_tool class="AngularRecursiveModuleImportExport" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 30 |
+
<inspection_tool class="AngularUndefinedBinding" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 31 |
+
<inspection_tool class="AngularUndefinedModuleExport" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 32 |
+
<inspection_tool class="AngularUndefinedTag" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 33 |
+
<inspection_tool class="AngularUnresolvedPipe" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 34 |
+
<inspection_tool class="AngularUnsupportedSyntax" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 35 |
+
<inspection_tool class="AngularUnusedComponentImport" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 36 |
+
<inspection_tool class="BadExpressionStatementJS" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 37 |
+
<inspection_tool class="CallerJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 38 |
+
<inspection_tool class="CommaExpressionJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 39 |
+
<inspection_tool class="ConstantConditionalExpressionJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 40 |
+
<inspection_tool class="ContinueOrBreakFromFinallyBlockJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 41 |
+
<inspection_tool class="CssBrowserCompatibilityForProperties" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 42 |
+
<inspection_tool class="CssConvertColorToHexInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 43 |
+
<inspection_tool class="CssConvertColorToRgbInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 44 |
+
<inspection_tool class="CssInvalidNestedSelector" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 45 |
+
<inspection_tool class="CssMissingSemicolon" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 46 |
+
<inspection_tool class="CyclomaticComplexityInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 47 |
+
<inspection_tool class="DjangoUnresolvedUrlInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
| 48 |
+
<inspection_tool class="DuplicatePropertyInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 49 |
+
<inspection_tool class="ES6BindWithArrowFunction" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 50 |
+
<inspection_tool class="ES6ClassMemberInitializationOrder" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 51 |
+
<inspection_tool class="ES6ConvertIndexedForToForOf" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 52 |
+
<inspection_tool class="ES6ConvertLetToConst" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 53 |
+
<inspection_tool class="ES6ConvertModuleExportToExport" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 54 |
+
<inspection_tool class="ES6ConvertRequireIntoImport" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 55 |
+
<inspection_tool class="ES6ConvertToForOf" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 56 |
+
<inspection_tool class="ES6ConvertVarToLetConst" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 57 |
+
<inspection_tool class="ES6DestructuringVariablesMerge" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 58 |
+
<inspection_tool class="ES6MissingAwait" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 59 |
+
<inspection_tool class="ES6PossiblyAsyncFunction" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 60 |
+
<inspection_tool class="ES6PreferShortImport" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 61 |
+
<inspection_tool class="ES6RedundantAwait" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 62 |
+
<inspection_tool class="ES6RedundantNestingInTemplateLiteral" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 63 |
+
<inspection_tool class="ES6ShorthandObjectProperty" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 64 |
+
<inspection_tool class="ES6UnusedImports" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 65 |
+
<inspection_tool class="EmptyDirectory" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 66 |
+
<inspection_tool class="EmptyStatementBodyJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 67 |
+
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 68 |
+
<inspection_tool class="ExceptionCaughtLocallyJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 69 |
+
<inspection_tool class="FallThroughInSwitchStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 70 |
+
<inspection_tool class="FlowJSConfig" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 71 |
+
<inspection_tool class="FlowJSFlagCommentPlacement" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 72 |
+
<inspection_tool class="HtmlNonExistentInternetResource" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 73 |
+
<inspection_tool class="HtmlPresentationalElement" enabled="true" level="INFORMATION" enabled_by_default="true" />
|
| 74 |
+
<inspection_tool class="HtmlRequiredSummaryAttribute" enabled="true" level="INFORMATION" enabled_by_default="true" />
|
| 75 |
+
<inspection_tool class="HtmlRequiredTitleAttribute" enabled="true" level="INFORMATION" enabled_by_default="true" />
|
| 76 |
+
<inspection_tool class="IncompatibleMaskJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 77 |
+
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 78 |
+
<inspection_tool class="IncorrectFormatting" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
| 79 |
+
<inspection_tool class="InfiniteLoopJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 80 |
+
<inspection_tool class="InfiniteRecursionJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 81 |
+
<inspection_tool class="JSAccessibilityCheck" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 82 |
+
<inspection_tool class="JSAnnotator" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 83 |
+
<inspection_tool class="JSArrowFunctionBracesCanBeRemoved" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 84 |
+
<inspection_tool class="JSAssignmentUsedAsCondition" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 85 |
+
<inspection_tool class="JSBitwiseOperatorUsage" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 86 |
+
<inspection_tool class="JSCheckFunctionSignatures" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 87 |
+
<inspection_tool class="JSClosureCompilerSyntax" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 88 |
+
<inspection_tool class="JSCommentMatchesSignature" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 89 |
+
<inspection_tool class="JSComparisonWithNaN" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 90 |
+
<inspection_tool class="JSConsecutiveCommasInArrayLiteral" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 91 |
+
<inspection_tool class="JSConstantReassignment" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 92 |
+
<inspection_tool class="JSDeprecatedSymbols" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 93 |
+
<inspection_tool class="JSDuplicateCaseLabel" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 94 |
+
<inspection_tool class="JSDuplicatedDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 95 |
+
<inspection_tool class="JSEqualityComparisonWithCoercion" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 96 |
+
<inspection_tool class="JSFileReferences" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 97 |
+
<inspection_tool class="JSFunctionExpressionToArrowFunction" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 98 |
+
<inspection_tool class="JSIgnoredPromiseFromCall" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 99 |
+
<inspection_tool class="JSIncompatibleTypesComparison" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 100 |
+
<inspection_tool class="JSJQueryEfficiency" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 101 |
+
<inspection_tool class="JSJoinVariableDeclarationAndAssignment" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 102 |
+
<inspection_tool class="JSLastCommaInArrayLiteral" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 103 |
+
<inspection_tool class="JSLastCommaInObjectLiteral" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 104 |
+
<inspection_tool class="JSMethodCanBeStatic" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 105 |
+
<inspection_tool class="JSMismatchedCollectionQueryUpdate" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 106 |
+
<inspection_tool class="JSMissingSwitchBranches" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 107 |
+
<inspection_tool class="JSMissingSwitchDefault" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 108 |
+
<inspection_tool class="JSNonASCIINames" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 109 |
+
<inspection_tool class="JSObjectNullOrUndefined" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 110 |
+
<inspection_tool class="JSOctalInteger" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 111 |
+
<inspection_tool class="JSPotentiallyInvalidConstructorUsage" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 112 |
+
<inspection_tool class="JSPotentiallyInvalidTargetOfIndexedPropertyAccess" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 113 |
+
<inspection_tool class="JSPotentiallyInvalidUsageOfClassThis" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 114 |
+
<inspection_tool class="JSPotentiallyInvalidUsageOfThis" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 115 |
+
<inspection_tool class="JSPrimitiveTypeWrapperUsage" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 116 |
+
<inspection_tool class="JSRedundantSwitchStatement" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 117 |
+
<inspection_tool class="JSReferencingMutableVariableFromClosure" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 118 |
+
<inspection_tool class="JSRemoveUnnecessaryParentheses" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 119 |
+
<inspection_tool class="JSStringConcatenationToES6Template" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 120 |
+
<inspection_tool class="JSSuspiciousEqPlus" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 121 |
+
<inspection_tool class="JSSuspiciousNameCombination" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 122 |
+
<inspection_tool class="JSSwitchVariableDeclarationIssue" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 123 |
+
<inspection_tool class="JSTestFailedLine" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 124 |
+
<inspection_tool class="JSTypeOfValues" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 125 |
+
<inspection_tool class="JSUndeclaredVariable" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 126 |
+
<inspection_tool class="JSUndefinedPropertyAssignment" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 127 |
+
<inspection_tool class="JSUnnecessarySemicolon" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 128 |
+
<inspection_tool class="JSUnreachableSwitchBranches" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 129 |
+
<inspection_tool class="JSUnresolvedExtXType" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 130 |
+
<inspection_tool class="JSUnresolvedLibraryURL" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 131 |
+
<inspection_tool class="JSUnresolvedReference" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 132 |
+
<inspection_tool class="JSUnusedAssignment" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 133 |
+
<inspection_tool class="JSUnusedGlobalSymbols" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 134 |
+
<inspection_tool class="JSUnusedLocalSymbols" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 135 |
+
<inspection_tool class="JSUrlImportUsage" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 136 |
+
<inspection_tool class="JSValidateJSDoc" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 137 |
+
<inspection_tool class="JSValidateTypes" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 138 |
+
<inspection_tool class="JSVoidFunctionReturnValueUsed" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 139 |
+
<inspection_tool class="JSXDomNesting" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 140 |
+
<inspection_tool class="JSXNamespaceValidation" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 141 |
+
<inspection_tool class="JSXUnresolvedComponent" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 142 |
+
<inspection_tool class="KarmaConfigFile" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 143 |
+
<inspection_tool class="LongLine" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 144 |
+
<inspection_tool class="LoopStatementThatDoesntLoopJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 145 |
+
<inspection_tool class="NodeCoreCodingAssistance" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 146 |
+
<inspection_tool class="NpmUsedModulesInstalled" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 147 |
+
<inspection_tool class="NpmVulnerableApiCode" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 148 |
+
<inspection_tool class="PackageJsonMismatchedDependency" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 149 |
+
<inspection_tool class="PointlessArithmeticExpressionJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 150 |
+
<inspection_tool class="PointlessBooleanExpressionJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 151 |
+
<inspection_tool class="PostCssCustomMedia" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 152 |
+
<inspection_tool class="PostCssCustomSelector" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 153 |
+
<inspection_tool class="PostCssMediaRange" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 154 |
+
<inspection_tool class="PostCssUnresolvedModuleValueReference" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 155 |
+
<inspection_tool class="ProblematicWhitespace" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 156 |
+
<inspection_tool class="PyArgumentEqualDefaultInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
| 157 |
+
<inspection_tool class="PyAugmentAssignmentInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
| 158 |
+
<inspection_tool class="PyClassicStyleClassInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 159 |
+
<inspection_tool class="PyCompatibilityInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
| 160 |
+
<option name="ourVersions">
|
| 161 |
+
<value>
|
| 162 |
+
<list size="5">
|
| 163 |
+
<item index="0" class="java.lang.String" itemvalue="3.14" />
|
| 164 |
+
<item index="1" class="java.lang.String" itemvalue="3.10" />
|
| 165 |
+
<item index="2" class="java.lang.String" itemvalue="3.11" />
|
| 166 |
+
<item index="3" class="java.lang.String" itemvalue="3.12" />
|
| 167 |
+
<item index="4" class="java.lang.String" itemvalue="3.13" />
|
| 168 |
+
</list>
|
| 169 |
+
</value>
|
| 170 |
+
</option>
|
| 171 |
+
</inspection_tool>
|
| 172 |
+
<inspection_tool class="PyMandatoryEncodingInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 173 |
+
<inspection_tool class="PyMissingOrEmptyDocstringInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
|
| 174 |
+
<inspection_tool class="PyMissingTypeHintsInspection" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="WARNING_ATTRIBUTES" />
|
| 175 |
+
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
| 176 |
+
<option name="ignoredErrors">
|
| 177 |
+
<list>
|
| 178 |
+
<option value="N812" />
|
| 179 |
+
</list>
|
| 180 |
+
</option>
|
| 181 |
+
</inspection_tool>
|
| 182 |
+
<inspection_tool class="PyTypeCheckerInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 183 |
+
<inspection_tool class="PydanticTypeCheckerInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 184 |
+
<inspection_tool class="RegExpAnonymousGroup" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 185 |
+
<inspection_tool class="ReservedWordUsedAsNameJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 186 |
+
<inspection_tool class="RestRoleInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
| 187 |
+
<option name="ignoredRoles">
|
| 188 |
+
<value>
|
| 189 |
+
<list size="0" />
|
| 190 |
+
</value>
|
| 191 |
+
</option>
|
| 192 |
+
</inspection_tool>
|
| 193 |
+
<inspection_tool class="ReturnFromFinallyBlockJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 194 |
+
<inspection_tool class="ShiftOutOfRangeJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 195 |
+
<inspection_tool class="SillyAssignmentJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 196 |
+
<inspection_tool class="SqlGotoInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 197 |
+
<inspection_tool class="SqlJoinCountInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 198 |
+
<inspection_tool class="SqlMissingColumnAliasesInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 199 |
+
<inspection_tool class="SqlNamedArgumentsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 200 |
+
<inspection_tool class="Stylelint" enabled="true" level="ERROR" enabled_by_default="true" />
|
| 201 |
+
<inspection_tool class="SuspiciousTypeOfGuard" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 202 |
+
<inspection_tool class="ThisExpressionReferencesGlobalObjectJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 203 |
+
<inspection_tool class="ThrowFromFinallyBlockJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 204 |
+
<inspection_tool class="TodoComment" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 205 |
+
<inspection_tool class="TrivialConditionalJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 206 |
+
<inspection_tool class="TrivialIfJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 207 |
+
<inspection_tool class="TypeScriptAbstractClassConstructorCanBeMadeProtected" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 208 |
+
<inspection_tool class="TypeScriptCheckImport" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 209 |
+
<inspection_tool class="TypeScriptConfig" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 210 |
+
<inspection_tool class="TypeScriptDuplicateUnionOrIntersectionType" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 211 |
+
<inspection_tool class="TypeScriptExplicitMemberType" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 212 |
+
<inspection_tool class="TypeScriptFieldCanBeMadeReadonly" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 213 |
+
<inspection_tool class="TypeScriptJSXUnresolvedComponent" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 214 |
+
<inspection_tool class="TypeScriptLibrary" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 215 |
+
<inspection_tool class="TypeScriptMissingAugmentationImport" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 216 |
+
<inspection_tool class="TypeScriptMissingConfigOption" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 217 |
+
<inspection_tool class="TypeScriptRedundantGenericType" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 218 |
+
<inspection_tool class="TypeScriptSmartCast" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 219 |
+
<inspection_tool class="TypeScriptSuspiciousConstructorParameterAssignment" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 220 |
+
<inspection_tool class="TypeScriptUMDGlobal" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
| 221 |
+
<inspection_tool class="TypeScriptUnresolvedReference" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 222 |
+
<inspection_tool class="TypeScriptValidateGenericTypes" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 223 |
+
<inspection_tool class="TypeScriptValidateTypes" enabled="false" level="ERROR" enabled_by_default="false" />
|
| 224 |
+
<inspection_tool class="UnnecessaryContinueJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 225 |
+
<inspection_tool class="UnnecessaryLabelJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 226 |
+
<inspection_tool class="UnnecessaryLabelOnBreakStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 227 |
+
<inspection_tool class="UnnecessaryLabelOnContinueStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 228 |
+
<inspection_tool class="UnnecessaryLocalVariableJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 229 |
+
<inspection_tool class="UnnecessaryReturnJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 230 |
+
<inspection_tool class="UnreachableCodeJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 231 |
+
<inspection_tool class="UnusedDefine" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 232 |
+
<inspection_tool class="UpdateDependencyToLatestVersion" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
| 233 |
+
<inspection_tool class="UseEllipsisInPropertyInspection" enabled="true" level="WARNING" enabled_by_default="true" />
|
| 234 |
+
<inspection_tool class="WebpackConfigHighlighting" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 235 |
+
<inspection_tool class="WithStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
|
| 236 |
+
</profile>
|
| 237 |
+
</component>
|
.idea/inspectionProfiles/profiles_settings.xml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<component name="InspectionProjectProfileManager">
|
| 2 |
+
<settings>
|
| 3 |
+
<option name="USE_PROJECT_PROFILE" value="false" />
|
| 4 |
+
<version value="1.0" />
|
| 5 |
+
</settings>
|
| 6 |
+
</component>
|
.idea/misc.xml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
+
<project version="4">
|
| 3 |
+
<component name="Black">
|
| 4 |
+
<option name="sdkName" value="uv (chattr)" />
|
| 5 |
+
</component>
|
| 6 |
+
<component name="ProjectRootManager" version="2" project-jdk-name="uv (chattr)" project-jdk-type="Python SDK" />
|
| 7 |
+
<component name="RuffConfiguration">
|
| 8 |
+
<option name="enabled" value="true" />
|
| 9 |
+
</component>
|
| 10 |
+
<component name="TyConfiguration">
|
| 11 |
+
<option name="enabled" value="true" />
|
| 12 |
+
</component>
|
| 13 |
+
</project>
|
.idea/modules.xml
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
+
<project version="4">
|
| 3 |
+
<component name="ProjectModuleManager">
|
| 4 |
+
<modules>
|
| 5 |
+
<module fileurl="file://$PROJECT_DIR$/.idea/chattr.iml" filepath="$PROJECT_DIR$/.idea/chattr.iml" />
|
| 6 |
+
</modules>
|
| 7 |
+
</component>
|
| 8 |
+
</project>
|
.idea/vcs.xml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
| 2 |
+
<project version="4">
|
| 3 |
+
<component name="VcsDirectoryMappings">
|
| 4 |
+
<mapping directory="" vcs="Git" />
|
| 5 |
+
</component>
|
| 6 |
+
</project>
|
.pre-commit-config.yaml
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
repos:
|
| 2 |
+
- repo: https://github.com/Mergifyio/mergify-pre-commit
|
| 3 |
+
rev: 1.1.0
|
| 4 |
+
hooks:
|
| 5 |
+
- id: validate-mergify-config-location
|
| 6 |
+
- id: validate-mergify-config
|
| 7 |
+
- repo: https://github.com/ComPWA/taplo-pre-commit
|
| 8 |
+
rev: v0.9.3
|
| 9 |
+
hooks:
|
| 10 |
+
- id: taplo-format
|
| 11 |
+
args:
|
| 12 |
+
- --config
|
| 13 |
+
- .github/lint/.taplo.toml
|
| 14 |
+
- id: taplo-lint
|
| 15 |
+
args:
|
| 16 |
+
- --config
|
| 17 |
+
- .github/lint/.taplo.toml
|
| 18 |
+
- --default-schema-catalogs
|
| 19 |
+
- repo: https://github.com/igorshubovych/markdownlint-cli
|
| 20 |
+
rev: v0.47.0
|
| 21 |
+
hooks:
|
| 22 |
+
- id: markdownlint
|
| 23 |
+
args:
|
| 24 |
+
- --config
|
| 25 |
+
- .github/lint/.markdownlint.yaml
|
| 26 |
+
- id: markdownlint-fix
|
| 27 |
+
args:
|
| 28 |
+
- --config
|
| 29 |
+
- .github/lint/.markdownlint.yaml
|
| 30 |
+
- repo: https://github.com/adrienverge/yamllint
|
| 31 |
+
rev: v1.38.0
|
| 32 |
+
hooks:
|
| 33 |
+
- id: yamllint
|
| 34 |
+
args:
|
| 35 |
+
- --strict
|
| 36 |
+
- -c
|
| 37 |
+
- .github/lint/.yamllint.yaml
|
| 38 |
+
- repo: https://github.com/docker-compose-linter/pre-commit-dclint
|
| 39 |
+
rev: v3.1.0
|
| 40 |
+
hooks:
|
| 41 |
+
- id: dclint
|
| 42 |
+
args:
|
| 43 |
+
- --fix
|
| 44 |
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
| 45 |
+
rev: v6.0.0
|
| 46 |
+
hooks:
|
| 47 |
+
- id: check-yaml
|
| 48 |
+
- id: end-of-file-fixer
|
| 49 |
+
- id: trailing-whitespace
|
| 50 |
+
- id: check-added-large-files
|
| 51 |
+
- id: check-ast
|
| 52 |
+
- id: check-illegal-windows-names
|
| 53 |
+
- id: check-json
|
| 54 |
+
- id: check-merge-conflict
|
| 55 |
+
args:
|
| 56 |
+
- --assume-in-merge
|
| 57 |
+
- id: check-symlinks
|
| 58 |
+
- id: check-toml
|
| 59 |
+
- id: check-vcs-permalinks
|
| 60 |
+
- id: check-xml
|
| 61 |
+
- id: debug-statements
|
| 62 |
+
- id: destroyed-symlinks
|
| 63 |
+
- id: detect-private-key
|
| 64 |
+
- id: mixed-line-ending
|
| 65 |
+
args:
|
| 66 |
+
- --fix=lf
|
| 67 |
+
- id: pretty-format-json
|
| 68 |
+
args:
|
| 69 |
+
- --autofix
|
| 70 |
+
- repo: https://github.com/renovatebot/pre-commit-hooks
|
| 71 |
+
rev: 43.0.5
|
| 72 |
+
hooks:
|
| 73 |
+
- id: renovate-config-validator
|
| 74 |
+
args:
|
| 75 |
+
- --strict
|
| 76 |
+
- repo: https://github.com/astral-sh/uv-pre-commit
|
| 77 |
+
rev: 0.9.28
|
| 78 |
+
hooks:
|
| 79 |
+
- id: uv-lock
|
| 80 |
+
- id: uv-sync
|
| 81 |
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
| 82 |
+
rev: v0.14.14
|
| 83 |
+
hooks:
|
| 84 |
+
- id: ruff-check
|
| 85 |
+
args:
|
| 86 |
+
- --fix
|
| 87 |
+
- --config
|
| 88 |
+
- .github/lint/.ruff.toml
|
| 89 |
+
- id: ruff-format
|
| 90 |
+
args:
|
| 91 |
+
- --config
|
| 92 |
+
- .github/lint/.ruff.toml
|
| 93 |
+
- repo: https://github.com/facebook/pyrefly-pre-commit
|
| 94 |
+
rev: 0.50.1
|
| 95 |
+
hooks:
|
| 96 |
+
- id: pyrefly-check
|
| 97 |
+
- repo: https://github.com/lyz-code/yamlfix
|
| 98 |
+
rev: 1.19.1
|
| 99 |
+
hooks:
|
| 100 |
+
- id: yamlfix
|
| 101 |
+
args:
|
| 102 |
+
- -c
|
| 103 |
+
- .github/lint/.yamlfix.toml
|
| 104 |
+
- repo: https://github.com/rhysd/actionlint
|
| 105 |
+
rev: v1.7.10
|
| 106 |
+
hooks:
|
| 107 |
+
- id: actionlint-docker
|
| 108 |
+
- repo: https://github.com/trufflesecurity/trufflehog
|
| 109 |
+
rev: v3.92.5
|
| 110 |
+
hooks:
|
| 111 |
+
- id: trufflehog
|
| 112 |
+
- repo: https://github.com/hadolint/hadolint
|
| 113 |
+
rev: v2.14.0
|
| 114 |
+
hooks:
|
| 115 |
+
- id: hadolint-docker
|
| 116 |
+
args:
|
| 117 |
+
- -c
|
| 118 |
+
- .github/lint/.hadolint.yaml
|
.sonarlint/connectedMode.json
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"projectKey": "AlphaSphereDotAI_chatacter_backend_app",
|
| 3 |
+
"region": "EU",
|
| 4 |
+
"sonarCloudOrganization": "alphaspheredotai"
|
| 5 |
+
}
|
.vscode/launch.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
// Use IntelliSense to learn about possible attributes.
|
| 3 |
+
// Hover to view descriptions of existing attributes.
|
| 4 |
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
| 5 |
+
"version": "0.2.0",
|
| 6 |
+
"configurations": [
|
| 7 |
+
{
|
| 8 |
+
"name": "run: server",
|
| 9 |
+
"type": "debugpy",
|
| 10 |
+
"request": "launch",
|
| 11 |
+
"module": "${workspaceFolderBasename}",
|
| 12 |
+
"preLaunchTask": "uv sync",
|
| 13 |
+
"logToFile": true,
|
| 14 |
+
"env": {
|
| 15 |
+
"DOPPLER_ENV": "1"
|
| 16 |
+
}
|
| 17 |
+
}
|
| 18 |
+
]
|
| 19 |
+
}
|
.vscode/tasks.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
| 3 |
+
// for the documentation about the tasks.json format
|
| 4 |
+
"version": "2.0.0",
|
| 5 |
+
"tasks": [
|
| 6 |
+
{
|
| 7 |
+
"label": "uv sync",
|
| 8 |
+
"type": "shell",
|
| 9 |
+
"command": "uv",
|
| 10 |
+
"args": [
|
| 11 |
+
"sync"
|
| 12 |
+
]
|
| 13 |
+
}
|
| 14 |
+
]
|
| 15 |
+
}
|
.zed/tasks.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"args": [
|
| 4 |
+
"run",
|
| 5 |
+
"chattr"
|
| 6 |
+
],
|
| 7 |
+
"command": "uv",
|
| 8 |
+
"label": "Run Chattr",
|
| 9 |
+
"reveal_target": "center",
|
| 10 |
+
"shell": "system"
|
| 11 |
+
},
|
| 12 |
+
{
|
| 13 |
+
"args": [
|
| 14 |
+
"compose",
|
| 15 |
+
"-f",
|
| 16 |
+
"compose-dev.yaml",
|
| 17 |
+
"up"
|
| 18 |
+
],
|
| 19 |
+
"command": "docker",
|
| 20 |
+
"label": "Run Docker Compose",
|
| 21 |
+
"reveal_target": "center",
|
| 22 |
+
"shell": "system"
|
| 23 |
+
}
|
| 24 |
+
]
|
AGENTS.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Agent Guidelines for Chattr
|
| 2 |
+
|
| 3 |
+
[byterover-mcp]
|
| 4 |
+
|
| 5 |
+
## Byterover MCP Server Tools Reference
|
| 6 |
+
|
| 7 |
+
There are two main workflows with Byterover tools and recommended tool call strategies that you **MUST** follow precisely.
|
| 8 |
+
|
| 9 |
+
### Onboarding workflow
|
| 10 |
+
|
| 11 |
+
If users particularly ask you to start the onboarding process, you **MUST STRICTLY** follow these steps.
|
| 12 |
+
|
| 13 |
+
1. **ALWAYS USE** **byterover-check-handbook-existence** first to check if the byterover handbook already exists. If not, You **MUST** call **byterover-create-handbook** to create the byterover handbook.
|
| 14 |
+
2. If the byterover handbook already exists, first you **MUST** USE **byterover-check-handbook-sync** to analyze the gap between the current codebase and the existing byterover handbook.
|
| 15 |
+
3. Then **IMMEDIATELY USE** **byterover-update-handbook** to update these changes to the byterover handbook.
|
| 16 |
+
4. During the onboarding, you **MUST** use **byterover-list-modules** **FIRST** to get the available modules, and then **byterover-store-modules** and **byterover-update-modules** if there are new modules or changes to existing modules in the project.
|
| 17 |
+
|
| 18 |
+
### Planning workflow
|
| 19 |
+
|
| 20 |
+
Based on user request, you **MUST** follow these sequences of tool calls
|
| 21 |
+
|
| 22 |
+
1. If asked to continue an unfinished implementation, **CALL** **byterover-retrieve-active-plans** to find the most relevant active plan.
|
| 23 |
+
2. **CRITICAL PLAN PERSISTENCE RULE**: Once a user approves a plan, you **MUST IMMEDIATELY CALL** **byterover-save-implementation-plan** to save it.
|
| 24 |
+
3. Throughout the plan, you **MUST** run **byterover-retrieve-knowledge** several times to retrieve sufficient knowledge and context for the plan's tasks.
|
| 25 |
+
4. In addition, you might need to run **byterover-search-modules** and **byterover-update-modules** if the tasks require or update knowledge about certain modules. However, **byterover-retrieve-knowledge** should **ALWAYS** be considered **FIRST**.
|
| 26 |
+
5. **MUST** use **byterover-update-plan-progress** to mark tasks (and then the whole plan) as completed.
|
| 27 |
+
Example:
|
| 28 |
+
|
| 29 |
+
- Task: `byterover-update-plan-progress(plan_name="Feature X", task_name="Task 1", is_completed=true)`
|
| 30 |
+
- All done: `byterover-update-plan-progress(plan_name="Feature X", is_completed=true)`
|
| 31 |
+
|
| 32 |
+
1. Then, you might call **byterover-store-knowledge** to save knowledge and experience implemented throughout the plan or in important tasks.
|
| 33 |
+
2. During the plan's implementation, you **MUST** frequently call **byterover-think-about-collected-information** and **byterover-assess-context-completeness** to make sure you're on the right track and gather sufficient context for the tasks.
|
| 34 |
+
|
| 35 |
+
### Recommended Workflow Sequence
|
| 36 |
+
|
| 37 |
+
1. **MOST IMPORTANT**: **ALWAYS USE** **byterover-retrieve-knowledge** once or several times for **EACH TASK** of the plan to gather necessary context to complete that task.
|
| 38 |
+
2. **MOST IMPORTANT**: **ALWAYS USE** **byterover-store-knowledge** once or several times to store critical knowledge and context for future implementations
|
| 39 |
+
3. Over 15 provided tools, **byterover-retrieve-knowledge** and **byterover-store-knowledge** ARE the two main tools, which **MUST** be used regularly. You can use these two main tools outside the two main workflows for retrieval and storage purposes.
|
| 40 |
+
4. You **MUST** include phrases like **"According to Byterover memory layer"**, **"Based on memory extracted from Byterover"**, **"From Byterover memory tools"**, ... to explicitly showcase that these sources are from **Byterover**.
|
| 41 |
+
5. **Implementation & Progress Tracking** → Execute implementation following saved plan → Mark tasks complete as you go → Mark entire plan done when all tasks finished.
|
| 42 |
+
6. You **MUST** use **byterover-update-module** **IMMEDIATELY** on changes to the module's purposes, technical details, or critical insights that essential for future implementations.
|
| 43 |
+
|
| 44 |
+
## Build/Lint/Test Commands
|
| 45 |
+
|
| 46 |
+
### Installation
|
| 47 |
+
|
| 48 |
+
```bash
|
| 49 |
+
uv sync # Install dependencies
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
### Building
|
| 53 |
+
|
| 54 |
+
```bash
|
| 55 |
+
uv build # Build source and wheel distributions
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
### Linting & Formatting
|
| 59 |
+
|
| 60 |
+
```bash
|
| 61 |
+
trunk fmt --all --no-progress # Auto-format code
|
| 62 |
+
trunk check # Run all linters and checks
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
### Testing
|
| 66 |
+
|
| 67 |
+
```bash
|
| 68 |
+
pytest # Run all tests
|
| 69 |
+
pytest tests/test_app.py::test_app # Run single test
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
## Code Style Guidelines
|
| 73 |
+
|
| 74 |
+
### General
|
| 75 |
+
|
| 76 |
+
- **Line length**: 88 characters
|
| 77 |
+
- **Indentation**: 4 spaces
|
| 78 |
+
- **Quote style**: Double quotes (`"`)
|
| 79 |
+
- **File encoding**: UTF-8
|
| 80 |
+
|
| 81 |
+
### Imports
|
| 82 |
+
|
| 83 |
+
- Use `from __future__ import annotations` when needed
|
| 84 |
+
- Group imports: standard library, third-party, local
|
| 85 |
+
- Use `TYPE_CHECKING` for conditional imports
|
| 86 |
+
- Combine as imports: `from typing import Dict, List` → `from typing import Dict, List`
|
| 87 |
+
|
| 88 |
+
### Type Hints
|
| 89 |
+
|
| 90 |
+
- Use type hints for all function parameters and return values
|
| 91 |
+
- Use `Self` for methods returning the same class instance
|
| 92 |
+
- Use `Sequence`, `list`, `dict` instead of bare generics
|
| 93 |
+
- Use `Path` from `pathlib` for file paths
|
| 94 |
+
|
| 95 |
+
### Naming Conventions
|
| 96 |
+
|
| 97 |
+
- **Functions/Methods**: `snake_case`
|
| 98 |
+
- **Variables**: `snake_case`
|
| 99 |
+
- **Classes**: `PascalCase`
|
| 100 |
+
- **Constants**: `UPPER_CASE`
|
| 101 |
+
- **Private attributes**: `_leading_underscore`
|
| 102 |
+
|
| 103 |
+
### Error Handling
|
| 104 |
+
|
| 105 |
+
- Use specific exception types (e.g., `OSError`, `ValueError`, `ValidationError`)
|
| 106 |
+
- Log errors with appropriate levels (`logger.error`, `logger.warning`)
|
| 107 |
+
- Raise `Error` from gradio for user-facing errors
|
| 108 |
+
- Use try/except blocks with meaningful error messages
|
| 109 |
+
|
| 110 |
+
### Async/Await
|
| 111 |
+
|
| 112 |
+
- Use `async def` for coroutines
|
| 113 |
+
- Use `await` for async operations
|
| 114 |
+
- Return `AsyncGenerator` for streaming responses
|
| 115 |
+
|
| 116 |
+
### Documentation
|
| 117 |
+
|
| 118 |
+
- Use docstrings for all public functions, classes, and modules
|
| 119 |
+
- Follow Google-style docstring format
|
| 120 |
+
- Document parameters, return values, and exceptions
|
| 121 |
+
|
| 122 |
+
### Logging
|
| 123 |
+
|
| 124 |
+
- Import logger from module settings
|
| 125 |
+
- Use appropriate log levels: `debug`, `info`, `warning`, `error`
|
| 126 |
+
- Include relevant context in log messages
|
| 127 |
+
|
| 128 |
+
### Testing Guidelines
|
| 129 |
+
|
| 130 |
+
- Use `pytest` framework
|
| 131 |
+
- Test functions named `test_*`
|
| 132 |
+
- Use descriptive assertions
|
| 133 |
+
- Mock external dependencies when needed
|
Dockerfile
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM cgr.dev/chainguard/wolfi-base:latest@sha256:17ab0709456ce1a2aedd85e95f72e58d73133bb70c33ae945a4d4b2424e984f1 AS builder
|
| 2 |
+
|
| 3 |
+
ARG INSTALL_SOURCE
|
| 4 |
+
ARG PYTHON_VERSION
|
| 5 |
+
|
| 6 |
+
# skipcq: DOK-DL3018
|
| 7 |
+
RUN apk add --no-cache build-base git uv
|
| 8 |
+
|
| 9 |
+
USER nonroot
|
| 10 |
+
|
| 11 |
+
RUN --mount=type=cache,target=/root/.cache/uv \
|
| 12 |
+
uv tool install ${INSTALL_SOURCE} --python ${PYTHON_VERSION}
|
| 13 |
+
|
| 14 |
+
FROM cgr.dev/chainguard/wolfi-base:latest@sha256:17ab0709456ce1a2aedd85e95f72e58d73133bb70c33ae945a4d4b2424e984f1 AS production
|
| 15 |
+
|
| 16 |
+
ENV GRADIO_SERVER_PORT=7860 \
|
| 17 |
+
GRADIO_SERVER_NAME=0.0.0.0 \
|
| 18 |
+
FASTEMBED_CACHE_PATH=/home/nonroot/fastembed \
|
| 19 |
+
PATH=/home/nonroot/.local/bin:$PATH
|
| 20 |
+
|
| 21 |
+
# skipcq: DOK-DL3018
|
| 22 |
+
RUN apk add --no-cache curl libstdc++
|
| 23 |
+
|
| 24 |
+
USER nonroot
|
| 25 |
+
|
| 26 |
+
WORKDIR /home/nonroot
|
| 27 |
+
|
| 28 |
+
COPY --from=builder --chown=nonroot:nonroot --chmod=555 /home/nonroot/.local/ /home/nonroot/.local/
|
| 29 |
+
|
| 30 |
+
EXPOSE ${GRADIO_SERVER_PORT}
|
| 31 |
+
|
| 32 |
+
CMD ["chattr"]
|
README.md
CHANGED
|
@@ -1,12 +1,38 @@
|
|
| 1 |
---
|
| 2 |
title: Chattr
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
-
sdk:
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
pinned: false
|
| 10 |
---
|
| 11 |
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
title: Chattr
|
| 3 |
+
emoji: 💬
|
| 4 |
+
colorFrom: gray
|
| 5 |
+
colorTo: blue
|
| 6 |
+
sdk: docker
|
| 7 |
+
app_port: 7860
|
| 8 |
+
short_description: Chat with Characters
|
|
|
|
| 9 |
---
|
| 10 |
|
| 11 |
+
## **Chattr**: App part of the Chatacter Backend
|
| 12 |
+
|
| 13 |
+
[](https://github.com/AlphaSphereDotAI/chattr/actions/workflows/build.yaml)
|
| 14 |
+
[](https://github.com/AlphaSphereDotAI/chattr/actions/workflows/ci_tools.yaml)
|
| 15 |
+
[](https://github.com/AlphaSphereDotAI/chattr/actions/workflows/github-code-scanning/codeql)
|
| 16 |
+
[](https://github.com/AlphaSphereDotAI/chattr/actions/workflows/dependabot/dependabot-updates)
|
| 17 |
+
[](https://github.com/AlphaSphereDotAI/chattr/actions/workflows/release.yaml)
|
| 18 |
+
[](https://github.com/AlphaSphereDotAI/chattr/actions/workflows/test.yaml)
|
| 19 |
+
|
| 20 |
+
### Environment Variables
|
| 21 |
+
|
| 22 |
+
The configuration of the server is done using environment variables:
|
| 23 |
+
|
| 24 |
+
| Name | Description | Required | Default Value |
|
| 25 |
+
|:---------------------------|:---------------------------------|:--------:|:-------------------------------------------|
|
| 26 |
+
| `MODEL__URL` | OpenAI-compatible endpoint | ✘ | `https://api.groq.com/openai/v1` |
|
| 27 |
+
| `MODEL__NAME` | Model name to use for chat | ✘ | `llama3-70b-8192` |
|
| 28 |
+
| `MODEL__API_KEY` | API key for model access | ✔ | `None` |
|
| 29 |
+
| `MODEL__TEMPERATURE` | Model temperature (0.0-1.0) | ✘ | `0.0` |
|
| 30 |
+
| `SHORT_TERM_MEMORY__URL` | Redis URL for memory store | ✘ | `redis://localhost:6379` |
|
| 31 |
+
| `VECTOR_DATABASE__NAME` | Vector database collection name | ✘ | `chattr` |
|
| 32 |
+
| `VOICE_GENERATOR_MCP__URL` | MCP service for audio generation | ✘ | `http://localhost:8001/gradio_api/mcp/sse` |
|
| 33 |
+
| `VIDEO_GENERATOR_MCP__URL` | MCP service for video generation | ✘ | `http://localhost:8002/gradio_api/mcp/sse` |
|
| 34 |
+
| `DIRECTORY__ASSETS` | Base assets directory | ✘ | `./assets` |
|
| 35 |
+
| `DIRECTORY__LOG` | Log files directory | ✘ | `./logs` |
|
| 36 |
+
| `DIRECTORY__IMAGE` | Image assets directory | ✘ | `./assets/image` |
|
| 37 |
+
| `DIRECTORY__AUDIO` | Audio assets directory | ✘ | `./assets/audio` |
|
| 38 |
+
| `DIRECTORY__VIDEO` | Video assets directory | ✘ | `./assets/video` |
|
assets/image/Einstein.jpg
ADDED
|
Git LFS Details
|
assets/image/Napoleon.jpg
ADDED
|
assets/prompts/template.poml
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<poml syntax="markdown">
|
| 2 |
+
<role speaker="system">
|
| 3 |
+
You are a helpful assistant who can act and mimic {{character}}'s character and answer questions about the era.
|
| 4 |
+
</role>
|
| 5 |
+
<task speaker="system">
|
| 6 |
+
Always respond to the user's query by first generating your text answer, then using an MCP to generate audio from that text, and finally using an MCP to create a video from that audio.
|
| 7 |
+
<br />
|
| 8 |
+
<b>Crucially, your final output MUST include the generated text response, followed by the tool call for the video creation.</b>
|
| 9 |
+
<list>
|
| 10 |
+
<item><b>Personality:</b> Adopt the voice, tone, and perspective of {{character}}.</item>
|
| 11 |
+
<item><b>Knowledge:</b> Answer questions about the {{character}} era, military campaigns, and French history relevant to his life.</item>
|
| 12 |
+
</list>
|
| 13 |
+
<stepwise-instructions>
|
| 14 |
+
<list>
|
| 15 |
+
<item>Understand the user's question and context.</item>
|
| 16 |
+
<item>Gather relevant information and resources.</item>
|
| 17 |
+
<item>Formulate a clear and concise response in {{character}}'s voice.</item>
|
| 18 |
+
<item><b>ALWAYS</b> generate audio from the formulated response using the appropriate MCP.</item>
|
| 19 |
+
<item><b>ALWAYS</b> create a video file from the generated audio using the appropriate MCP.</item>
|
| 20 |
+
</list>
|
| 21 |
+
</stepwise-instructions>
|
| 22 |
+
</task>
|
| 23 |
+
<output-format>
|
| 24 |
+
Your response structure MUST be:
|
| 25 |
+
<list>
|
| 26 |
+
<item><b>[{{character}}'s Text Response]</b></item>
|
| 27 |
+
<item><b>[Tool Call to generate the video, which implicitly includes the audio generation step]</b></item>
|
| 28 |
+
</list>
|
| 29 |
+
</output-format>
|
| 30 |
+
</poml>
|
docker-compose-dev.yaml
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Chattr Dev
|
| 2 |
+
services:
|
| 3 |
+
vector_database:
|
| 4 |
+
image: qdrant/qdrant:latest@sha256:0425e3e03e7fd9b3dc95c4214546afe19de2eb2e28ca621441a56663ac6e1f46
|
| 5 |
+
ports:
|
| 6 |
+
- 6333:6333
|
| 7 |
+
- 6334:6334
|
| 8 |
+
volumes:
|
| 9 |
+
- qdrant_storage:/qdrant/storage
|
| 10 |
+
restart: on-failure:3
|
| 11 |
+
voice_generator:
|
| 12 |
+
image: ghcr.io/alphaspheredotai/vocalizr:latest@sha256:df1f4fa0615ae3f34249454ddc3a74e3fd955332da507ff2c7d5373190037863
|
| 13 |
+
ports:
|
| 14 |
+
- 7861:7860
|
| 15 |
+
post_start:
|
| 16 |
+
- command: chown -R nonroot:nonroot /home/nonroot
|
| 17 |
+
user: root
|
| 18 |
+
- command: chmod -R 700 /home/nonroot
|
| 19 |
+
user: root
|
| 20 |
+
volumes:
|
| 21 |
+
- huggingface:/home/nonroot/hf
|
| 22 |
+
- results:/home/nonroot/results
|
| 23 |
+
- logs:/home/nonroot/logs
|
| 24 |
+
restart: on-failure:3
|
| 25 |
+
environment:
|
| 26 |
+
GRADIO_DEBUG: 1
|
| 27 |
+
healthcheck:
|
| 28 |
+
test:
|
| 29 |
+
- CMD
|
| 30 |
+
- curl
|
| 31 |
+
- -o
|
| 32 |
+
- /dev/null
|
| 33 |
+
- -f
|
| 34 |
+
- -s
|
| 35 |
+
- -w
|
| 36 |
+
- "'Status: %{http_code},\tTime: %{time_total}s'"
|
| 37 |
+
- http://localhost:7860/
|
| 38 |
+
interval: 1m30s
|
| 39 |
+
timeout: 10s
|
| 40 |
+
retries: 5
|
| 41 |
+
start_period: 40s
|
| 42 |
+
deploy:
|
| 43 |
+
resources:
|
| 44 |
+
reservations:
|
| 45 |
+
devices:
|
| 46 |
+
- driver: nvidia
|
| 47 |
+
count: all
|
| 48 |
+
capabilities:
|
| 49 |
+
- gpu
|
| 50 |
+
video_generator:
|
| 51 |
+
image: ghcr.io/alphaspheredotai/visualizr:latest@sha256:2c5b096a66c6ebee1a5c0242a8b42c393e0cfdcda086ae6ceba11f92618ec7aa
|
| 52 |
+
ports:
|
| 53 |
+
- 7862:7860
|
| 54 |
+
volumes:
|
| 55 |
+
- assets:/home/nonroot/assets
|
| 56 |
+
- checkpoint:/home/nonroot/ckpts
|
| 57 |
+
- gfpgan:/home/nonroot/gfpgan
|
| 58 |
+
post_start:
|
| 59 |
+
- command: chown -R nonroot:nonroot /home/nonroot
|
| 60 |
+
user: root
|
| 61 |
+
- command: chmod -R 700 /home/nonroot
|
| 62 |
+
user: root
|
| 63 |
+
restart: on-failure:3
|
| 64 |
+
environment:
|
| 65 |
+
GRADIO_DEBUG: 1
|
| 66 |
+
healthcheck:
|
| 67 |
+
test:
|
| 68 |
+
- CMD
|
| 69 |
+
- curl
|
| 70 |
+
- -o
|
| 71 |
+
- /dev/null
|
| 72 |
+
- -f
|
| 73 |
+
- -s
|
| 74 |
+
- -w
|
| 75 |
+
- "'Status: %{http_code},\tTime: %{time_total}s'"
|
| 76 |
+
- http://localhost:7860/
|
| 77 |
+
interval: 1m30s
|
| 78 |
+
timeout: 10s
|
| 79 |
+
retries: 5
|
| 80 |
+
start_period: 40s
|
| 81 |
+
deploy:
|
| 82 |
+
resources:
|
| 83 |
+
reservations:
|
| 84 |
+
devices:
|
| 85 |
+
- driver: nvidia
|
| 86 |
+
count: all
|
| 87 |
+
capabilities:
|
| 88 |
+
- gpu
|
| 89 |
+
volumes:
|
| 90 |
+
logs:
|
| 91 |
+
assets:
|
| 92 |
+
fastembed:
|
| 93 |
+
qdrant_storage:
|
| 94 |
+
checkpoint:
|
| 95 |
+
gfpgan:
|
| 96 |
+
huggingface:
|
| 97 |
+
results:
|
docker-compose.yaml
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Chattr
|
| 2 |
+
services:
|
| 3 |
+
chattr:
|
| 4 |
+
image: alphaspheredotai/chattr:latest@sha256:094981de2f6cbad9b42bbde8147a1278af0e5a681b1d1903c497e1cd6e8dcb2c
|
| 5 |
+
volumes:
|
| 6 |
+
- logs:/home/nonroot/logs
|
| 7 |
+
- assets:/home/nonroot/assets
|
| 8 |
+
- fastembed:/home/nonroot/fastembed
|
| 9 |
+
environment:
|
| 10 |
+
MODEL__URL: ${MODEL__URL:-https://generativelanguage.googleapis.com/v1beta/openai}
|
| 11 |
+
MODEL__NAME: ${MODEL__NAME:-gemini-2.5-flash}
|
| 12 |
+
MODEL__API_KEY: ${MODEL__API_KEY}
|
| 13 |
+
VECTOR_DATABASE__URL: http://vector_database:6333
|
| 14 |
+
VECTOR_DATABASE__NAME: main
|
| 15 |
+
ports:
|
| 16 |
+
- 7860:7860
|
| 17 |
+
restart: on-failure:3
|
| 18 |
+
healthcheck:
|
| 19 |
+
test:
|
| 20 |
+
- CMD
|
| 21 |
+
- curl
|
| 22 |
+
- -o
|
| 23 |
+
- /dev/null
|
| 24 |
+
- -f
|
| 25 |
+
- -s
|
| 26 |
+
- -w
|
| 27 |
+
- "'Status: %{http_code},\tTime: %{time_total}s'"
|
| 28 |
+
- http://localhost:7860/
|
| 29 |
+
interval: 1m30s
|
| 30 |
+
timeout: 10s
|
| 31 |
+
retries: 5
|
| 32 |
+
start_period: 40s
|
| 33 |
+
post_start:
|
| 34 |
+
- command: chown -R nonroot:nonroot /home/nonroot
|
| 35 |
+
user: root
|
| 36 |
+
- command: chmod -R 700 /home/nonroot
|
| 37 |
+
user: root
|
| 38 |
+
vector_database:
|
| 39 |
+
image: qdrant/qdrant:latest@sha256:0425e3e03e7fd9b3dc95c4214546afe19de2eb2e28ca621441a56663ac6e1f46
|
| 40 |
+
volumes:
|
| 41 |
+
- qdrant_storage:/qdrant/storage
|
| 42 |
+
ports:
|
| 43 |
+
- 6333:6333
|
| 44 |
+
- 6334:6334
|
| 45 |
+
restart: on-failure:3
|
| 46 |
+
video_generator:
|
| 47 |
+
image: alphaspheredotai/visualizr:latest@sha256:d1f5c97d9babdbdd45ca26b6ec42a128b612921295de13d77cb7e36fe638bb55
|
| 48 |
+
volumes:
|
| 49 |
+
- assets:/home/nonroot/assets
|
| 50 |
+
- checkpoint:/home/nonroot/ckpts
|
| 51 |
+
- gfpgan:/home/nonroot/gfpgan
|
| 52 |
+
ports:
|
| 53 |
+
- 7862:7860
|
| 54 |
+
restart: on-failure:3
|
| 55 |
+
healthcheck:
|
| 56 |
+
test:
|
| 57 |
+
- CMD
|
| 58 |
+
- curl
|
| 59 |
+
- -o
|
| 60 |
+
- /dev/null
|
| 61 |
+
- -f
|
| 62 |
+
- -s
|
| 63 |
+
- -w
|
| 64 |
+
- "'Status: %{http_code},\tTime: %{time_total}s'"
|
| 65 |
+
- http://localhost:7860/
|
| 66 |
+
interval: 1m30s
|
| 67 |
+
timeout: 10s
|
| 68 |
+
retries: 5
|
| 69 |
+
start_period: 40s
|
| 70 |
+
deploy:
|
| 71 |
+
resources:
|
| 72 |
+
reservations:
|
| 73 |
+
devices:
|
| 74 |
+
- driver: nvidia
|
| 75 |
+
count: all
|
| 76 |
+
capabilities:
|
| 77 |
+
- gpu
|
| 78 |
+
post_start:
|
| 79 |
+
- command: chown -R nonroot:nonroot /home/nonroot
|
| 80 |
+
user: root
|
| 81 |
+
- command: chmod -R 700 /home/nonroot
|
| 82 |
+
user: root
|
| 83 |
+
voice_generator:
|
| 84 |
+
image: alphaspheredotai/vocalizr:latest@sha256:e508d563372b08766b9dd38f462c97ec831d5563922255baf911b2c821a77c8a
|
| 85 |
+
volumes:
|
| 86 |
+
- huggingface:/home/nonroot/hf
|
| 87 |
+
- results:/home/nonroot/results
|
| 88 |
+
- logs:/home/nonroot/logs
|
| 89 |
+
ports:
|
| 90 |
+
- 7861:7860
|
| 91 |
+
restart: on-failure:3
|
| 92 |
+
healthcheck:
|
| 93 |
+
test:
|
| 94 |
+
- CMD
|
| 95 |
+
- curl
|
| 96 |
+
- -o
|
| 97 |
+
- /dev/null
|
| 98 |
+
- -f
|
| 99 |
+
- -s
|
| 100 |
+
- -w
|
| 101 |
+
- "'Status: %{http_code},\tTime: %{time_total}s'"
|
| 102 |
+
- http://localhost:7860/
|
| 103 |
+
interval: 1m30s
|
| 104 |
+
timeout: 10s
|
| 105 |
+
retries: 5
|
| 106 |
+
start_period: 40s
|
| 107 |
+
deploy:
|
| 108 |
+
resources:
|
| 109 |
+
reservations:
|
| 110 |
+
devices:
|
| 111 |
+
- driver: nvidia
|
| 112 |
+
count: all
|
| 113 |
+
capabilities:
|
| 114 |
+
- gpu
|
| 115 |
+
post_start:
|
| 116 |
+
- command: chown -R nonroot:nonroot /home/nonroot
|
| 117 |
+
user: root
|
| 118 |
+
- command: chmod -R 700 /home/nonroot
|
| 119 |
+
user: root
|
| 120 |
+
volumes:
|
| 121 |
+
logs:
|
| 122 |
+
assets:
|
| 123 |
+
fastembed:
|
| 124 |
+
qdrant_storage:
|
| 125 |
+
checkpoint:
|
| 126 |
+
gfpgan:
|
mcp.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"mcp_servers": [
|
| 3 |
+
{
|
| 4 |
+
"args": [
|
| 5 |
+
"run",
|
| 6 |
+
"-i",
|
| 7 |
+
"--rm",
|
| 8 |
+
"mcp/time"
|
| 9 |
+
],
|
| 10 |
+
"command": "docker",
|
| 11 |
+
"name": "time",
|
| 12 |
+
"transport": "stdio",
|
| 13 |
+
"type": "command"
|
| 14 |
+
},
|
| 15 |
+
{
|
| 16 |
+
"args": [
|
| 17 |
+
"run",
|
| 18 |
+
"-i",
|
| 19 |
+
"--rm",
|
| 20 |
+
"mcp/sequentialthinking"
|
| 21 |
+
],
|
| 22 |
+
"command": "docker",
|
| 23 |
+
"name": "sequential_thinking",
|
| 24 |
+
"transport": "stdio",
|
| 25 |
+
"type": "command"
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"name": "voice_generator",
|
| 29 |
+
"transport": "streamable-http",
|
| 30 |
+
"type": "url",
|
| 31 |
+
"url": "http://localhost:7861/gradio_api/mcp"
|
| 32 |
+
},
|
| 33 |
+
{
|
| 34 |
+
"name": "video_generator",
|
| 35 |
+
"transport": "streamable-http",
|
| 36 |
+
"type": "url",
|
| 37 |
+
"url": "http://localhost:7862/gradio_api/mcp/?tools=generate_video_mcp"
|
| 38 |
+
}
|
| 39 |
+
]
|
| 40 |
+
}
|
pyproject.toml
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[project]
|
| 2 |
+
authors = [
|
| 3 |
+
{ email = "mohamed.hisham.abdelzaher@gmail.com", name = "Mohamed Hisham Abdelzaher" },
|
| 4 |
+
]
|
| 5 |
+
dependencies = [
|
| 6 |
+
"agno[google,qdrant]>=2.4.7",
|
| 7 |
+
"ddgs>=9.10.0",
|
| 8 |
+
"fastembed>=0.7.4",
|
| 9 |
+
"gradio[mcp]>=6.5.1",
|
| 10 |
+
"m3u8>=6.0.0",
|
| 11 |
+
"mem0ai>=1.0.2",
|
| 12 |
+
"poml>=0.0.8",
|
| 13 |
+
"rich>=14.3.1",
|
| 14 |
+
]
|
| 15 |
+
description = "App part of the Chatacter Backend"
|
| 16 |
+
name = "chattr"
|
| 17 |
+
readme = "README.md"
|
| 18 |
+
requires-python = ">=3.13,<3.14"
|
| 19 |
+
version = "0.0.103"
|
| 20 |
+
|
| 21 |
+
[project.scripts]
|
| 22 |
+
chattr = "chattr.__main__:main"
|
| 23 |
+
|
| 24 |
+
[build-system]
|
| 25 |
+
build-backend = "uv_build"
|
| 26 |
+
requires = ["uv_build"]
|
| 27 |
+
|
| 28 |
+
[dependency-groups]
|
| 29 |
+
dev = [
|
| 30 |
+
"doppler-env>=0.3.1",
|
| 31 |
+
"pre-commit>=4.5.1",
|
| 32 |
+
"pytest-emoji>=0.2.0",
|
| 33 |
+
"pytest-md>=0.2.0",
|
| 34 |
+
"pytest-mergify>=2026.1.26.1",
|
| 35 |
+
"ruff>=0.14.14",
|
| 36 |
+
"ty>=0.0.14",
|
| 37 |
+
"uv-build>=0.9.28",
|
| 38 |
+
]
|
| 39 |
+
|
| 40 |
+
[tool.ruff]
|
| 41 |
+
extend = ".github/lint/.ruff.toml"
|
src/chattr/__init__.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from warnings import filterwarnings
|
| 2 |
+
|
| 3 |
+
from rich.console import Console
|
| 4 |
+
|
| 5 |
+
filterwarnings("ignore", category=DeprecationWarning)
|
| 6 |
+
|
| 7 |
+
console = Console()
|
| 8 |
+
APP_NAME: str = __package__
|
src/chattr/__main__.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import TYPE_CHECKING
|
| 2 |
+
|
| 3 |
+
from chattr.app.runner import app
|
| 4 |
+
|
| 5 |
+
if TYPE_CHECKING:
|
| 6 |
+
from gradio import Blocks
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def main() -> None:
|
| 10 |
+
"""Launch the Gradio Multi-agent system app."""
|
| 11 |
+
application: Blocks = app.gui()
|
| 12 |
+
application.queue(api_open=True)
|
| 13 |
+
application.launch(
|
| 14 |
+
debug=True,
|
| 15 |
+
enable_monitoring=True,
|
| 16 |
+
show_error=True,
|
| 17 |
+
pwa=True,
|
| 18 |
+
)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
if __name__ == "__main__":
|
| 22 |
+
main()
|
src/chattr/app/__init__.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from gradio.processing_utils import PUBLIC_HOSTNAME_WHITELIST
|
| 2 |
+
|
| 3 |
+
PUBLIC_HOSTNAME_WHITELIST.append("localhost")
|
src/chattr/app/builder.py
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Main orchestration graph for the Chattr application."""
|
| 2 |
+
|
| 3 |
+
from collections.abc import AsyncGenerator
|
| 4 |
+
from json import dumps, loads
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
|
| 7 |
+
from agno.agent import (
|
| 8 |
+
Agent,
|
| 9 |
+
RunContentEvent,
|
| 10 |
+
ToolCallCompletedEvent,
|
| 11 |
+
ToolCallStartedEvent,
|
| 12 |
+
)
|
| 13 |
+
from agno.db import BaseDb
|
| 14 |
+
from agno.db.json import JsonDb
|
| 15 |
+
from agno.guardrails import PIIDetectionGuardrail, PromptInjectionGuardrail
|
| 16 |
+
from agno.knowledge.knowledge import Knowledge
|
| 17 |
+
from agno.models.message import Message
|
| 18 |
+
from agno.models.openai.like import OpenAILike
|
| 19 |
+
from agno.tools import Toolkit
|
| 20 |
+
from agno.tools.mcp import MultiMCPTools
|
| 21 |
+
from agno.vectordb.qdrant import Qdrant
|
| 22 |
+
from gradio import (
|
| 23 |
+
Audio,
|
| 24 |
+
Blocks,
|
| 25 |
+
ChatInterface,
|
| 26 |
+
ChatMessage,
|
| 27 |
+
Error,
|
| 28 |
+
Video,
|
| 29 |
+
)
|
| 30 |
+
from gradio.components.chatbot import MetadataDict
|
| 31 |
+
from m3u8 import M3U8, load
|
| 32 |
+
from poml import poml
|
| 33 |
+
from pydantic import HttpUrl, ValidationError
|
| 34 |
+
from requests import Session
|
| 35 |
+
from rich.pretty import pprint
|
| 36 |
+
|
| 37 |
+
from chattr.app.settings import Settings, logger
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
class App:
|
| 41 |
+
"""Main application class for the Chattr Multi-agent system app."""
|
| 42 |
+
|
| 43 |
+
def __init__(self, settings: Settings) -> None:
|
| 44 |
+
self.settings = settings
|
| 45 |
+
|
| 46 |
+
async def _setup_agent(self) -> Agent:
|
| 47 |
+
return Agent(
|
| 48 |
+
model=self._setup_model(),
|
| 49 |
+
tools=await self._setup_tools(),
|
| 50 |
+
description="You are a helpful assistant who can act and mimic Napoleon's character and answer questions about the era.",
|
| 51 |
+
instructions=[
|
| 52 |
+
"Understand the user's question and context.",
|
| 53 |
+
"Gather relevant information and resources.",
|
| 54 |
+
"Formulate a clear and concise response in Napoleon's voice.",
|
| 55 |
+
"ALWAYS generate audio from the formulated response using the appropriate Tool.",
|
| 56 |
+
"Generate video from the resulted audio using the appropriate Tool.",
|
| 57 |
+
],
|
| 58 |
+
db=self._setup_database(),
|
| 59 |
+
knowledge=self._setup_knowledge(
|
| 60 |
+
self._setup_vector_database(),
|
| 61 |
+
self._setup_database(),
|
| 62 |
+
),
|
| 63 |
+
markdown=True,
|
| 64 |
+
add_datetime_to_context=True,
|
| 65 |
+
timezone_identifier="Africa/Cairo",
|
| 66 |
+
pre_hooks=[PIIDetectionGuardrail(), PromptInjectionGuardrail()],
|
| 67 |
+
debug_mode=True,
|
| 68 |
+
save_response_to_file="agno/response.txt",
|
| 69 |
+
add_history_to_context=True,
|
| 70 |
+
add_memories_to_context=True,
|
| 71 |
+
)
|
| 72 |
+
|
| 73 |
+
async def _setup_tools(self) -> list[Toolkit]:
|
| 74 |
+
mcp_servers: list[dict] = loads(self.settings.mcp.path.read_text()).get(
|
| 75 |
+
"mcp_servers",
|
| 76 |
+
[],
|
| 77 |
+
)
|
| 78 |
+
url_servers = [m for m in mcp_servers if m.get("type") == "url"]
|
| 79 |
+
self.mcp_tools = MultiMCPTools(
|
| 80 |
+
urls=[m.get("url") for m in url_servers],
|
| 81 |
+
urls_transports=[m.get("transport") for m in url_servers],
|
| 82 |
+
)
|
| 83 |
+
await self.mcp_tools.connect()
|
| 84 |
+
return [self.mcp_tools]
|
| 85 |
+
|
| 86 |
+
def _setup_prompt(self) -> str:
|
| 87 |
+
prompt_template = poml(
|
| 88 |
+
self.settings.directory.prompts / "template.poml",
|
| 89 |
+
{"character": "Napoleon"},
|
| 90 |
+
chat=False,
|
| 91 |
+
format="dict",
|
| 92 |
+
)
|
| 93 |
+
if not isinstance(prompt_template, dict):
|
| 94 |
+
_msg = "Prompt template must be a string."
|
| 95 |
+
raise TypeError(_msg)
|
| 96 |
+
return prompt_template["messages"]
|
| 97 |
+
|
| 98 |
+
def _setup_model(self) -> OpenAILike:
|
| 99 |
+
"""
|
| 100 |
+
Initialize the ChatOpenAI language model using the provided settings.
|
| 101 |
+
|
| 102 |
+
This method creates and returns a ChatOpenAI instance configured with
|
| 103 |
+
the model's URL, name, API key, and temperature.
|
| 104 |
+
|
| 105 |
+
Returns:
|
| 106 |
+
ChatOpenAI: The initialized ChatOpenAI language model instance.
|
| 107 |
+
|
| 108 |
+
Raises:
|
| 109 |
+
Exception: If the model initialization fails.
|
| 110 |
+
"""
|
| 111 |
+
try:
|
| 112 |
+
return OpenAILike(
|
| 113 |
+
base_url=str(self.settings.model.url),
|
| 114 |
+
id=self.settings.model.name,
|
| 115 |
+
api_key=self.settings.model.api_key.get_secret_value(),
|
| 116 |
+
temperature=self.settings.model.temperature,
|
| 117 |
+
)
|
| 118 |
+
except Exception as e:
|
| 119 |
+
_msg: str = f"Failed to initialize ChatOpenAI model: {e}"
|
| 120 |
+
logger.error(_msg)
|
| 121 |
+
raise Error(_msg) from e
|
| 122 |
+
|
| 123 |
+
def _setup_vector_database(self) -> Qdrant:
|
| 124 |
+
return Qdrant(
|
| 125 |
+
collection=self.settings.vector_database.name,
|
| 126 |
+
url=self.settings.vector_database.url.host,
|
| 127 |
+
)
|
| 128 |
+
|
| 129 |
+
def _setup_knowledge(self, vector_db: Qdrant, db: BaseDb) -> Knowledge:
|
| 130 |
+
return Knowledge(
|
| 131 |
+
vector_db=vector_db,
|
| 132 |
+
contents_db=db,
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
def _setup_database(self) -> JsonDb:
|
| 136 |
+
return JsonDb(
|
| 137 |
+
db_path="agno",
|
| 138 |
+
)
|
| 139 |
+
|
| 140 |
+
def gui(self) -> Blocks:
|
| 141 |
+
"""
|
| 142 |
+
Create and return the main Gradio Blocks interface for the Chattr app.
|
| 143 |
+
|
| 144 |
+
Returns:
|
| 145 |
+
Blocks: The constructed Gradio Blocks interface for the chat application.
|
| 146 |
+
"""
|
| 147 |
+
return ChatInterface(fn=self.generate_response, save_history=True)
|
| 148 |
+
|
| 149 |
+
async def generate_response(
|
| 150 |
+
self,
|
| 151 |
+
message: str,
|
| 152 |
+
history: list[ChatMessage],
|
| 153 |
+
) -> AsyncGenerator[tuple[str, list[ChatMessage], Path | None, Path | None]]:
|
| 154 |
+
"""
|
| 155 |
+
Generate a response to a user message and update the conversation history.
|
| 156 |
+
|
| 157 |
+
This asynchronous method streams responses from the state graph and
|
| 158 |
+
yields updated history and audio file paths as needed.
|
| 159 |
+
|
| 160 |
+
Args:
|
| 161 |
+
message: The user's input message as a string.
|
| 162 |
+
history: The conversation history as a list of ChatMessage objects.
|
| 163 |
+
|
| 164 |
+
Returns:
|
| 165 |
+
AsyncGenerator: Yields a tuple containing an
|
| 166 |
+
empty string, the updated history, and
|
| 167 |
+
a Path to an audio file if generated.
|
| 168 |
+
"""
|
| 169 |
+
try:
|
| 170 |
+
agent: Agent = await self._setup_agent()
|
| 171 |
+
async for response in agent.arun(
|
| 172 |
+
Message(content=message, role="user"),
|
| 173 |
+
stream=True,
|
| 174 |
+
):
|
| 175 |
+
pprint(response)
|
| 176 |
+
if isinstance(response, RunContentEvent):
|
| 177 |
+
history.append(
|
| 178 |
+
ChatMessage(
|
| 179 |
+
role="assistant",
|
| 180 |
+
content=response.content,
|
| 181 |
+
),
|
| 182 |
+
)
|
| 183 |
+
elif isinstance(response, ToolCallStartedEvent):
|
| 184 |
+
history.append(
|
| 185 |
+
ChatMessage(
|
| 186 |
+
role="assistant",
|
| 187 |
+
content=dumps(response.tool.tool_args, indent=4),
|
| 188 |
+
metadata=MetadataDict(
|
| 189 |
+
title=response.tool.tool_name,
|
| 190 |
+
id=response.tool.tool_call_id,
|
| 191 |
+
duration=response.tool.created_at,
|
| 192 |
+
),
|
| 193 |
+
),
|
| 194 |
+
)
|
| 195 |
+
elif isinstance(response, ToolCallCompletedEvent):
|
| 196 |
+
if response.tool.tool_call_error:
|
| 197 |
+
history.append(
|
| 198 |
+
ChatMessage(
|
| 199 |
+
role="assistant",
|
| 200 |
+
content=dumps(response.tool.tool_args, indent=4),
|
| 201 |
+
metadata=MetadataDict(
|
| 202 |
+
title=response.tool.tool_name,
|
| 203 |
+
id=response.tool.tool_call_id,
|
| 204 |
+
log="Tool Call Failed",
|
| 205 |
+
duration=response.tool.metrics.duration,
|
| 206 |
+
),
|
| 207 |
+
),
|
| 208 |
+
)
|
| 209 |
+
else:
|
| 210 |
+
history.append(
|
| 211 |
+
ChatMessage(
|
| 212 |
+
role="assistant",
|
| 213 |
+
content=dumps(response.tool.tool_args, indent=4),
|
| 214 |
+
metadata=MetadataDict(
|
| 215 |
+
title=response.tool.tool_name,
|
| 216 |
+
id=response.tool.tool_call_id,
|
| 217 |
+
log="Tool Call Succeeded",
|
| 218 |
+
duration=response.tool.metrics.duration,
|
| 219 |
+
),
|
| 220 |
+
),
|
| 221 |
+
)
|
| 222 |
+
if response.tool.tool_name == "generate_audio_for_text":
|
| 223 |
+
history.append(
|
| 224 |
+
Audio(
|
| 225 |
+
response.tool.result,
|
| 226 |
+
autoplay=True,
|
| 227 |
+
show_download_button=True,
|
| 228 |
+
show_share_button=True,
|
| 229 |
+
),
|
| 230 |
+
)
|
| 231 |
+
elif response.tool.tool_name == "generate_video_mcp":
|
| 232 |
+
history.append(
|
| 233 |
+
Video(
|
| 234 |
+
response.tool.result,
|
| 235 |
+
autoplay=True,
|
| 236 |
+
show_download_button=True,
|
| 237 |
+
show_share_button=True,
|
| 238 |
+
),
|
| 239 |
+
)
|
| 240 |
+
else:
|
| 241 |
+
msg = f"Unknown tool name: {response.tool.tool_name}"
|
| 242 |
+
raise Error(msg)
|
| 243 |
+
yield history
|
| 244 |
+
except Exception as e:
|
| 245 |
+
_msg: str = f"Error generating response: {e}"
|
| 246 |
+
logger.error(_msg)
|
| 247 |
+
raise Error(_msg) from e
|
| 248 |
+
finally:
|
| 249 |
+
await self._close()
|
| 250 |
+
|
| 251 |
+
def _is_url(self, value: str | None) -> bool:
|
| 252 |
+
"""
|
| 253 |
+
Check if a string is a valid URL.
|
| 254 |
+
|
| 255 |
+
Args:
|
| 256 |
+
value: The string to check. Can be None.
|
| 257 |
+
|
| 258 |
+
Returns:
|
| 259 |
+
bool: True if the string is a valid URL, False otherwise.
|
| 260 |
+
"""
|
| 261 |
+
if value is None:
|
| 262 |
+
return False
|
| 263 |
+
|
| 264 |
+
try:
|
| 265 |
+
_ = HttpUrl(value)
|
| 266 |
+
except ValidationError:
|
| 267 |
+
return False
|
| 268 |
+
return True
|
| 269 |
+
|
| 270 |
+
def _download_file(self, url: HttpUrl, path: Path) -> None:
|
| 271 |
+
"""
|
| 272 |
+
Download a file from a URL and save it to a local path.
|
| 273 |
+
|
| 274 |
+
Args:
|
| 275 |
+
url: The URL to download the file from.
|
| 276 |
+
path: The local file path where the downloaded file will be saved.
|
| 277 |
+
|
| 278 |
+
Returns:
|
| 279 |
+
None
|
| 280 |
+
|
| 281 |
+
Raises:
|
| 282 |
+
requests.RequestException: If the HTTP request fails.
|
| 283 |
+
IOError: If file writing fails.
|
| 284 |
+
"""
|
| 285 |
+
if str(url).endswith(".m3u8"):
|
| 286 |
+
_playlist: M3U8 = load(url)
|
| 287 |
+
url: str = str(url).replace("playlist.m3u8", _playlist.segments[0].uri)
|
| 288 |
+
logger.info(f"Downloading {url} to {path}")
|
| 289 |
+
session = Session()
|
| 290 |
+
response = session.get(url, stream=True, timeout=30)
|
| 291 |
+
response.raise_for_status()
|
| 292 |
+
with path.open("wb") as f:
|
| 293 |
+
for chunk in response.iter_content(chunk_size=8192):
|
| 294 |
+
if chunk:
|
| 295 |
+
f.write(chunk)
|
| 296 |
+
logger.info(f"File downloaded to {path}")
|
| 297 |
+
|
| 298 |
+
async def _close(self) -> None:
|
| 299 |
+
try:
|
| 300 |
+
logger.info("Closing MCP tools...")
|
| 301 |
+
await self.mcp_tools.close()
|
| 302 |
+
except Exception as e:
|
| 303 |
+
msg: str = (
|
| 304 |
+
f"Error closing MCP tools: {e}, Check if the Tool services are running."
|
| 305 |
+
)
|
| 306 |
+
logger.error(msg)
|
| 307 |
+
raise Error(msg) from e
|
| 308 |
+
|
| 309 |
+
|
| 310 |
+
async def test() -> None:
|
| 311 |
+
settings: Settings = Settings()
|
| 312 |
+
app: App = App(settings)
|
| 313 |
+
agent: Agent = await app._setup_agent()
|
| 314 |
+
try:
|
| 315 |
+
await agent.aprint_response("Hello!", debug_mode=True)
|
| 316 |
+
finally:
|
| 317 |
+
await app._close()
|
| 318 |
+
|
| 319 |
+
|
| 320 |
+
if __name__ == "__main__":
|
| 321 |
+
import asyncio
|
| 322 |
+
|
| 323 |
+
asyncio.run(test())
|
src/chattr/app/logger.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from logging import INFO, WARNING, Logger, basicConfig, getLogger
|
| 2 |
+
|
| 3 |
+
from rich.logging import RichHandler
|
| 4 |
+
|
| 5 |
+
from chattr import APP_NAME, console
|
| 6 |
+
|
| 7 |
+
basicConfig(
|
| 8 |
+
level=INFO,
|
| 9 |
+
handlers=[
|
| 10 |
+
RichHandler(
|
| 11 |
+
level=INFO,
|
| 12 |
+
console=console,
|
| 13 |
+
rich_tracebacks=True,
|
| 14 |
+
),
|
| 15 |
+
],
|
| 16 |
+
format="%(name)s | %(process)d | %(message)s",
|
| 17 |
+
)
|
| 18 |
+
getLogger("httpx").setLevel(WARNING)
|
| 19 |
+
logger: Logger = getLogger(APP_NAME)
|