@hej / sigit / commits / 68653a2

Add release workflow, update license, and bump version to 0.1.1

Seto Elkahfi committed Apr 14, 2026 at 20:01 UTC 68653a2f7c52a3a0b785363e3b3d82462d17209e
4 files changed +439 -44
.github/workflows/release.yml new
+189
@@ -0,0 +1,189 @@
1 +name: Release
2 +
3 +on:
4 + push:
5 + tags:
6 + - "v*.*.*"
7 + workflow_dispatch:
8 + inputs:
9 + tag:
10 + description: "Release tag (e.g. v0.1.0)"
11 + required: true
12 +
13 +permissions:
14 + contents: write
15 +
16 +env:
17 + CARGO_TERM_COLOR: always
18 +
19 +jobs:
20 + build:
21 + name: Build ${{ matrix.artifact }}
22 + runs-on: ${{ matrix.os }}
23 + strategy:
24 + fail-fast: false
25 + matrix:
26 + include:
27 + - target: aarch64-apple-darwin
28 + os: macos-latest
29 + artifact: sigit-darwin-aarch64
30 + binary: sigit
31 + archive_ext: tar.gz
32 +
33 + - target: x86_64-apple-darwin
34 + os: macos-13
35 + artifact: sigit-darwin-x86_64
36 + binary: sigit
37 + archive_ext: tar.gz
38 +
39 + - target: x86_64-unknown-linux-gnu
40 + os: ubuntu-latest
41 + artifact: sigit-linux-x86_64
42 + binary: sigit
43 + archive_ext: tar.gz
44 +
45 + - target: aarch64-unknown-linux-gnu
46 + os: ubuntu-24.04-arm
47 + artifact: sigit-linux-aarch64
48 + binary: sigit
49 + archive_ext: tar.gz
50 +
51 + - target: x86_64-pc-windows-msvc
52 + os: windows-latest
53 + artifact: sigit-windows-x86_64
54 + binary: sigit.exe
55 + archive_ext: zip
56 +
57 + steps:
58 + - name: Checkout
59 + uses: actions/checkout@v6
60 + with:
61 + ref: ${{ github.event.inputs.tag || github.ref }}
62 +
63 + - name: Set release version
64 + shell: bash
65 + run: |
66 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
67 + release_version="${GITHUB_REF_NAME#v}"
68 + else
69 + release_version="${{ github.event.inputs.tag }}"
70 + release_version="${release_version#v}"
71 + fi
72 +
73 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
74 +
75 + - name: Verify Cargo.toml version matches tag
76 + shell: bash
77 + run: |
78 + CARGO_VERSION=$(cargo metadata --no-deps --format-version 1 \
79 + | jq -r '.packages[] | select(.name == "sigit") | .version')
80 +
81 + echo "Cargo.toml version : ${CARGO_VERSION}"
82 + echo "Release tag version: ${RELEASE_VERSION}"
83 +
84 + if [[ "${CARGO_VERSION}" != "${RELEASE_VERSION}" ]]; then
85 + echo "::error::Version mismatch — bump Cargo.toml version before tagging."
86 + exit 1
87 + fi
88 +
89 + - name: Install Rust toolchain
90 + uses: dtolnay/rust-toolchain@stable
91 + with:
92 + targets: ${{ matrix.target }}
93 +
94 + - name: Setup Rust cache
95 + uses: Swatinem/rust-cache@v2
96 + with:
97 + key: release-${{ matrix.target }}
98 +
99 + - name: Build
100 + shell: bash
101 + run: cargo build --release --locked --target ${{ matrix.target }}
102 +
103 + - name: Package (tar.gz)
104 + if: matrix.archive_ext == 'tar.gz'
105 + shell: bash
106 + run: |
107 + binary="target/${{ matrix.target }}/release/${{ matrix.binary }}"
108 + archive="${{ matrix.artifact }}.tar.gz"
109 +
110 + tar -czf "${archive}" -C "$(dirname "${binary}")" "${{ matrix.binary }}"
111 +
112 + echo "ARCHIVE=${archive}" >> "$GITHUB_ENV"
113 +
114 + - name: Package (zip)
115 + if: matrix.archive_ext == 'zip'
116 + shell: pwsh
117 + run: |
118 + $binary = "target\${{ matrix.target }}\release\${{ matrix.binary }}"
119 + $archive = "${{ matrix.artifact }}.zip"
120 +
121 + Compress-Archive -Path $binary -DestinationPath $archive
122 +
123 + "ARCHIVE=$archive" | Out-File -FilePath $env:GITHUB_ENV -Append
124 +
125 + - name: Upload archive
126 + uses: actions/upload-artifact@v4
127 + with:
128 + name: ${{ matrix.artifact }}
129 + path: ${{ env.ARCHIVE }}
130 + if-no-files-found: error
131 + retention-days: 1
132 +
133 + release:
134 + name: Publish GitHub Release
135 + needs: build
136 + runs-on: ubuntu-latest
137 + permissions:
138 + contents: write
139 +
140 + steps:
141 + - name: Checkout
142 + uses: actions/checkout@v6
143 + with:
144 + ref: ${{ github.event.inputs.tag || github.ref }}
145 +
146 + - name: Set release version and tag
147 + shell: bash
148 + run: |
149 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
150 + release_tag="${GITHUB_REF_NAME}"
151 + release_version="${GITHUB_REF_NAME#v}"
152 + else
153 + release_tag="${{ github.event.inputs.tag }}"
154 + release_version="${{ github.event.inputs.tag }}"
155 + release_version="${release_version#v}"
156 + fi
157 +
158 + echo "RELEASE_TAG=${release_tag}" >> "$GITHUB_ENV"
159 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
160 +
161 + - name: Download all archives
162 + uses: actions/download-artifact@v4
163 + with:
164 + path: archives
165 + merge-multiple: true
166 +
167 + - name: Check whether release already exists
168 + id: release-check
169 + shell: bash
170 + run: |
171 + if gh release view "${RELEASE_TAG}" --repo "${{ github.repository }}" >/dev/null 2>&1; then
172 + echo "Release ${RELEASE_TAG} already exists — skipping."
173 + echo "exists=true" >> "$GITHUB_OUTPUT"
174 + else
175 + echo "exists=false" >> "$GITHUB_OUTPUT"
176 + fi
177 + env:
178 + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
179 +
180 + - name: Create release and upload archives
181 + if: steps.release-check.outputs.exists != 'true'
182 + shell: bash
183 + run: |
184 + gh release create "${RELEASE_TAG}" \
185 + --title "siGit ${RELEASE_TAG}" \
186 + --generate-notes \
187 + archives/*
188 + env:
189 + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Cargo.lock
+57 -41
@@ -1056,16 +1056,15 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
1056
1057 [[package]]
1058 name = "crossterm"
1059 -version = "0.28.1"
1059 +version = "0.25.0"
1060 source = "registry+https://github.com/rust-lang/crates.io-index"
1061 -checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
1061 +checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
1062 dependencies = [
1063 - "bitflags 2.11.0",
1063 + "bitflags 1.3.2",
1064 "crossterm_winapi",
1065 - "futures-core",
1066 - "mio",
1065 + "libc",
1066 + "mio 0.8.11",
1067 "parking_lot",
1068 - "rustix 0.38.44",
1068 "signal-hook",
1069 "signal-hook-mio",
1070 "winapi",
@@ -1073,17 +1072,16 @@ dependencies = [
1072
1073 [[package]]
1074 name = "crossterm"
1076 -version = "0.29.0"
1075 +version = "0.28.1"
1076 source = "registry+https://github.com/rust-lang/crates.io-index"
1078 -checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b"
1077 +checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
1078 dependencies = [
1079 "bitflags 2.11.0",
1080 "crossterm_winapi",
1082 - "derive_more",
1083 - "document-features",
1084 - "mio",
1081 + "futures-core",
1082 + "mio 1.2.0",
1083 "parking_lot",
1086 - "rustix 1.1.4",
1084 + "rustix 0.38.44",
1085 "signal-hook",
1086 "signal-hook-mio",
1087 "winapi",
@@ -1437,15 +1435,6 @@ version = "1.1.1"
1435 source = "registry+https://github.com/rust-lang/crates.io-index"
1436 checksum = "c2db04e74f0a9a93103b50e90b96024c9b2bdca8bce6a632ec71b88736d3d359"
1437
1440 -[[package]]
1441 -name = "document-features"
1442 -version = "0.2.12"
1443 -source = "registry+https://github.com/rust-lang/crates.io-index"
1444 -checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61"
1445 -dependencies = [
1446 - "litrs",
1447 -]
1448 -
1438 [[package]]
1439 name = "dtoa"
1440 version = "1.0.11"
@@ -3027,12 +3016,6 @@ version = "0.8.2"
3016 source = "registry+https://github.com/rust-lang/crates.io-index"
3017 checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
3018
3030 -[[package]]
3031 -name = "litrs"
3032 -version = "1.0.0"
3033 -source = "registry+https://github.com/rust-lang/crates.io-index"
3034 -checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
3035 -
3019 [[package]]
3020 name = "llguidance"
3021 version = "1.7.2"
@@ -3287,6 +3270,18 @@ dependencies = [
3270 "simd-adler32",
3271 ]
3272
3273 +[[package]]
3274 +name = "mio"
3275 +version = "0.8.11"
3276 +source = "registry+https://github.com/rust-lang/crates.io-index"
3277 +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
3278 +dependencies = [
3279 + "libc",
3280 + "log",
3281 + "wasi",
3282 + "windows-sys 0.48.0",
3283 +]
3284 +
3285 [[package]]
3286 name = "mio"
3287 version = "1.2.0"
@@ -3302,7 +3297,8 @@ dependencies = [
3297 [[package]]
3298 name = "mistralrs"
3299 version = "0.8.1"
3305 -source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#a27af8ea01123e5d5777120619413345989f4006"
3300 +source = "registry+https://github.com/rust-lang/crates.io-index"
3301 +checksum = "9bb0a83340b4492ebba9760ba6845364de369c7e10c1f91af8733d574c7405fa"
3302 dependencies = [
3303 "anyhow",
3304 "candle-core",
@@ -3329,7 +3325,8 @@ dependencies = [
3325 [[package]]
3326 name = "mistralrs-audio"
3327 version = "0.8.1"
3332 -source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#a27af8ea01123e5d5777120619413345989f4006"
3328 +source = "registry+https://github.com/rust-lang/crates.io-index"
3329 +checksum = "5ac5d36f634c7c20c45845bc995be3b6387ab01048410386a5b180cfeaf89c72"
3330 dependencies = [
3331 "anyhow",
3332 "apodize",
@@ -3340,7 +3337,8 @@ dependencies = [
3337 [[package]]
3338 name = "mistralrs-core"
3339 version = "0.8.1"
3343 -source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#a27af8ea01123e5d5777120619413345989f4006"
3340 +source = "registry+https://github.com/rust-lang/crates.io-index"
3341 +checksum = "a2b8b9e5c94491d9ceeded3a30291cb6af6ae74810a5776dd55e3bbb8b3429d4"
3342 dependencies = [
3343 "ahash",
3344 "akin",
@@ -3437,7 +3435,8 @@ dependencies = [
3435 [[package]]
3436 name = "mistralrs-macros"
3437 version = "0.8.1"
3440 -source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#a27af8ea01123e5d5777120619413345989f4006"
3438 +source = "registry+https://github.com/rust-lang/crates.io-index"
3439 +checksum = "5aa9b4794322d3f89fe61d21f33f67be494c16d5bd869604b111218f32544d32"
3440 dependencies = [
3441 "darling 0.23.0",
3442 "proc-macro2",
@@ -3448,7 +3447,8 @@ dependencies = [
3447 [[package]]
3448 name = "mistralrs-mcp"
3449 version = "0.8.1"
3451 -source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#a27af8ea01123e5d5777120619413345989f4006"
3450 +source = "registry+https://github.com/rust-lang/crates.io-index"
3451 +checksum = "4fa97d4e3189ed80ebbc730b7da5b2356df0ae004ab489066249340c33c089ab"
3452 dependencies = [
3453 "anyhow",
3454 "async-trait",
@@ -3468,7 +3468,8 @@ dependencies = [
3468 [[package]]
3469 name = "mistralrs-paged-attn"
3470 version = "0.8.1"
3471 -source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#a27af8ea01123e5d5777120619413345989f4006"
3471 +source = "registry+https://github.com/rust-lang/crates.io-index"
3472 +checksum = "6e53ddf1537426997b46abdadbe6ca8a7ce7668004ed2b7cf00115016558bae8"
3473 dependencies = [
3474 "anyhow",
3475 "candle-core",
@@ -3484,7 +3485,8 @@ dependencies = [
3485 [[package]]
3486 name = "mistralrs-quant"
3487 version = "0.8.1"
3487 -source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#a27af8ea01123e5d5777120619413345989f4006"
3488 +source = "registry+https://github.com/rust-lang/crates.io-index"
3489 +checksum = "980715493d252e9aaf0779c4c101576d67ef4dd9812bfd77a54987f6f17526f4"
3490 dependencies = [
3491 "byteorder",
3492 "candle-core",
@@ -3513,7 +3515,8 @@ dependencies = [
3515 [[package]]
3516 name = "mistralrs-vision"
3517 version = "0.8.1"
3516 -source = "git+https://github.com/setoelkahfi/mistral.rs?branch=fix%2Fall-platform-fixes#a27af8ea01123e5d5777120619413345989f4006"
3518 +source = "registry+https://github.com/rust-lang/crates.io-index"
3519 +checksum = "10046a3da2de5b702d3e829b5ddef7aa829ad454819dcc4876dea481a6cb5456"
3520 dependencies = [
3521 "candle-core",
3522 "image",
@@ -3827,7 +3830,9 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
3830
3831 [[package]]
3832 name = "onde"
3830 -version = "0.1.3"
3833 +version = "0.1.4"
3834 +source = "registry+https://github.com/rust-lang/crates.io-index"
3835 +checksum = "939495589fec914220491600a00bddedcba437e5fd5e3926ca1af2e8da681bb0"
3836 dependencies = [
3837 "anyhow",
3838 "cc",
@@ -5292,7 +5297,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
5297
5298 [[package]]
5299 name = "sigit"
5295 -version = "0.1.0"
5300 +version = "0.1.1"
5301 dependencies = [
5302 "agent-client-protocol",
5303 "anyhow",
@@ -5325,7 +5330,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
5330 checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc"
5331 dependencies = [
5332 "libc",
5328 - "mio",
5333 + "mio 0.8.11",
5334 + "mio 1.2.0",
5335 "signal-hook",
5336 ]
5337
@@ -6106,7 +6112,7 @@ checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c"
6112 dependencies = [
6113 "bytes",
6114 "libc",
6109 - "mio",
6115 + "mio 1.2.0",
6116 "parking_lot",
6117 "pin-project-lite",
6118 "signal-hook-registry",
@@ -6286,10 +6292,11 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
6292 [[package]]
6293 name = "tqdm"
6294 version = "0.8.0"
6289 -source = "git+https://github.com/setoelkahfi/tqdm?branch=deps%2Fbump-crossterm#41e4182829136e6dadbdd1c36af824d19219147a"
6295 +source = "registry+https://github.com/rust-lang/crates.io-index"
6296 +checksum = "b316d5c2ac649ca856dacd487d0ebb94f3b746bada51355d93dd2c007ab62a2e"
6297 dependencies = [
6298 "anyhow",
6292 - "crossterm 0.29.0",
6299 + "crossterm 0.25.0",
6300 "once_cell",
6301 ]
6302
@@ -7266,6 +7273,15 @@ dependencies = [
7273 "windows-targets 0.42.2",
7274 ]
7275
7276 +[[package]]
7277 +name = "windows-sys"
7278 +version = "0.48.0"
7279 +source = "registry+https://github.com/rust-lang/crates.io-index"
7280 +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
7281 +dependencies = [
7282 + "windows-targets 0.48.5",
7283 +]
7284 +
7285 [[package]]
7286 name = "windows-sys"
7287 version = "0.52.0"
Cargo.toml
+3 -3
@@ -1,10 +1,10 @@
1 [package]
2 name = "sigit"
3 -version = "0.1.0"
3 +version = "0.1.1"
4 edition = "2024"
5 description = "siGit Code — ACP-compatible AI coding agent for smbCloud platform."
6 documentation = "https://getsigit.5mb.app/"
7 -license = "MIT OR Apache-2.0"
7 +license = "Apache-2.0"
8
9 [[bin]]
10 name = "sigit"
@@ -15,7 +15,7 @@ path = "src/main.rs"
15 agent-client-protocol = "0.10.4"
16
17 # Onde Inference engine (local LLM)
18 -onde = { path = "../onde" }
18 +onde = { version = "0.1.4" }
19
20 # Async runtime
21 async-trait = "0.1"
LICENSE new
+190
@@ -0,0 +1,190 @@
1 + Apache License
2 + Version 2.0, January 2004
3 + http://www.apache.org/licenses/
4 +
5 + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 +
7 + 1. Definitions.
8 +
9 + "License" shall mean the terms and conditions for use, reproduction,
10 + and distribution as defined by Sections 1 through 9 of this document.
11 +
12 + "Licensor" shall mean the copyright owner or entity authorized by
13 + the copyright owner that is granting the License.
14 +
15 + "Legal Entity" shall mean the union of the acting entity and all
16 + other entities that control, are controlled by, or are under common
17 + control with that entity. For the purposes of this definition,
18 + "control" means (i) the power, direct or indirect, to cause the
19 + direction or management of such entity, whether by contract or
20 + otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 + outstanding shares, or (iii) beneficial ownership of such entity.
22 +
23 + "You" (or "Your") shall mean an individual or Legal Entity
24 + exercising permissions granted by this License.
25 +
26 + "Source" form shall mean the preferred form for making modifications,
27 + including but not limited to software source code, documentation
28 + source, and configuration files.
29 +
30 + "Object" form shall mean any form resulting from mechanical
31 + transformation or translation of a Source form, including but
32 + not limited to compiled object code, generated documentation,
33 + and conversions to other media types.
34 +
35 + "Work" shall mean the work of authorship made available under
36 + the License, as indicated by a copyright notice that is included in
37 + or attached to the work (an example is provided in the Appendix below).
38 +
39 + "Derivative Works" shall mean any work, whether in Source or Object
40 + form, that is based on (or derived from) the Work and for which the
41 + editorial revisions, annotations, elaborations, or other modifications
42 + represent, as a whole, an original work of authorship. For the purposes
43 + of this License, Derivative Works shall not include works that remain
44 + separable from, or merely link (or bind by name) to the interfaces of,
45 + the Work and Derivative Works thereof.
46 +
47 + "Contribution" shall mean, as defined by the copyright owner or by the
48 + Legal Entity authorized to submit on behalf of the copyright owner, any
49 + work of authorship, including the original version of the Work and any
50 + modifications or additions to that Work or Derivative Works of the Work.
51 +
52 + "Contributor" shall mean Licensor and any Legal Entity on behalf of
53 + whom a Contribution has been received by the Licensor and subsequently
54 + incorporated within the Work.
55 +
56 + 2. Grant of Copyright License. Subject to the terms and conditions of
57 + this License, each Contributor hereby grants to You a perpetual,
58 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable
59 + copyright license to reproduce, prepare Derivative Works of,
60 + publicly display, publicly perform, sublicense, and distribute the
61 + Work and such Derivative Works in Source or Object form.
62 +
63 + 3. Grant of Patent License. Subject to the terms and conditions of
64 + this License, each Contributor hereby grants to You a perpetual,
65 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable
66 + (except as stated in this section) patent license to make, have made,
67 + use, offer to sell, sell, import, and otherwise transfer the Work,
68 + where such license applies only to those patent claims licensable
69 + by such Contributor that are necessarily infringed by their
70 + Contribution(s) alone or by combination of their Contribution(s)
71 + with the Work to which such Contribution(s) was submitted. If You
72 + institute patent litigation against any entity (including a
73 + cross-claim or counterclaim in a lawsuit) alleging that the Work
74 + or a Contribution incorporated within the Work constitutes direct
75 + or contributory patent infringement, then any and all patent licenses
76 + granted to You under this License for that Work shall terminate
77 + as of the date such litigation is filed.
78 +
79 + 4. Redistribution. You may reproduce and distribute copies of the
80 + Work or Derivative Works thereof in any medium, with or without
81 + modifications, and in Source or Object form, provided that You
82 + meet the following conditions:
83 +
84 + (a) You must give any other recipients of the Work or
85 + Derivative Works a copy of this License; and
86 +
87 + (b) You must cause any modified files to carry prominent notices
88 + stating that You changed the files; and
89 +
90 + (c) You must retain, in the Source form of any Derivative Works
91 + that You distribute, all copyright, patent, trademark, and
92 + attribution notices from the Source form of the Work,
93 + excluding those notices that do not pertain to any part of
94 + the Derivative Works; and
95 +
96 + (d) If the Work includes a "NOTICE" text file as part of its
97 + distribution, You must include a readable copy of the
98 + attribution notices contained within such NOTICE file, in
99 + at least one of the following places: within a NOTICE text
100 + file distributed as part of the Derivative Works; within
101 + the Source form or documentation, if provided along with the
102 + Derivative Works; or, within a display generated by the
103 + Derivative Works, if and wherever such third-party notices
104 + normally appear. The contents of the NOTICE file are for
105 + informational purposes only and do not modify the License.
106 + You may add Your own attribution notices within Derivative
107 + Works that You distribute, alongside or as an addendum to
108 + the NOTICE text from the Work, provided that such additional
109 + attribution notices cannot be construed as modifying the License.
110 +
111 + You may add Your own license statement for Your modifications and
112 + may provide additional grant of rights to use, copy, modify, merge,
113 + publish, distribute, sublicense, and/or sell copies of the Work,
114 + and to permit persons to whom the Work is furnished to do so,
115 + subject to the following conditions:
116 +
117 + The above copyright notice and this permission notice shall be
118 + included in all copies or substantial portions of the Work.
119 +
120 + 5. Submission of Contributions. Unless You explicitly state otherwise,
121 + any Contribution intentionally submitted for inclusion in the Work
122 + by You to the Licensor shall be under the terms and conditions of
123 + this License, without any additional terms or conditions.
124 + Notwithstanding the above, nothing herein shall supersede or modify
125 + the terms of any separate license agreement you may have executed
126 + with Licensor regarding such Contributions.
127 +
128 + 6. Trademarks. This License does not grant permission to use the trade
129 + names, trademarks, service marks, or product names of the Licensor,
130 + except as required for reasonable and customary use in describing the
131 + origin of the Work and reproducing the content of the NOTICE file.
132 +
133 + 7. Disclaimer of Warranty. Unless required by applicable law or
134 + agreed to in writing, Licensor provides the Work (and each
135 + Contributor provides its Contributions) on an "AS IS" BASIS,
136 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
137 + implied, including, without limitation, any warranties or conditions
138 + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
139 + PARTICULAR PURPOSE. You are solely responsible for determining the
140 + appropriateness of using or redistributing the Work and assume any
141 + risks associated with Your exercise of permissions under this License.
142 +
143 + 8. Limitation of Liability. In no event and under no legal theory,
144 + whether in tort (including negligence), contract, or otherwise,
145 + unless required by applicable law (such as deliberate and grossly
146 + negligent acts) or agreed to in writing, shall any Contributor be
147 + liable to You for damages, including any direct, indirect, special,
148 + incidental, or exemplary damages of any character arising as a
149 + result of this License or out of the use or inability to use the
150 + Work (including but not limited to damages for loss of goodwill,
151 + work stoppage, computer failure or malfunction, or all other
152 + commercial damages or losses), even if such Contributor has been
153 + advised of the possibility of such damages.
154 +
155 + 9. Accepting Warranty or Additional Liability. While redistributing
156 + the Work or Derivative Works thereof, You may choose to offer,
157 + and charge a fee for, acceptance of support, warranty, indemnity,
158 + or other liability obligations and/or rights consistent with this
159 + License. However, in accepting such obligations, You may act only
160 + on Your own behalf and on Your sole responsibility, not on behalf
161 + of any other Contributor, and only if You agree to indemnify,
162 + defend, and hold each Contributor harmless for any liability
163 + incurred by, or claims asserted against, such Contributor by reason
164 + of your accepting any such warranty or additional liability.
165 +
166 + END OF TERMS AND CONDITIONS
167 +
168 + APPENDIX: How to apply the Apache License to your work.
169 +
170 + To apply the Apache License to your work, attach the following
171 + boilerplate notice, with the fields enclosed by brackets "[]"
172 + replaced with your own identifying information. (Don't include
173 + the brackets!) The text should be enclosed in the appropriate
174 + comment syntax for the file format in use. Also, it is recommended
175 + that a file or directory name be given on the same line as the
176 + copyright notice for easier identification within third-party archives.
177 +
178 + Copyright 2026 Seto Elkahfi
179 +
180 + Licensed under the Apache License, Version 2.0 (the "License");
181 + you may not use this file except in compliance with the License.
182 + You may obtain a copy of the License at
183 +
184 + http://www.apache.org/licenses/LICENSE-2.0
185 +
186 + Unless required by applicable law or agreed to in writing, software
187 + distributed under the License is distributed on an "AS IS" BASIS,
188 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
189 + See the License for the specific language governing permissions and
190 + limitations under the License.