piighost 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- piighost-0.1.0/.cz.toml +7 -0
- piighost-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +67 -0
- piighost-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +37 -0
- piighost-0.1.0/.github/pull_request_template.md +19 -0
- piighost-0.1.0/.github/workflows/ci.yml +52 -0
- piighost-0.1.0/.github/workflows/docs.yml +34 -0
- piighost-0.1.0/.github/workflows/release.yml +38 -0
- piighost-0.1.0/.gitignore +175 -0
- piighost-0.1.0/.python-version +1 -0
- piighost-0.1.0/CHANGELOG.md +20 -0
- piighost-0.1.0/CLAUDE.md +70 -0
- piighost-0.1.0/CODE_OF_CONDUCT.md +65 -0
- piighost-0.1.0/CONTRIBUTING.md +100 -0
- piighost-0.1.0/LICENSE +21 -0
- piighost-0.1.0/Makefile +16 -0
- piighost-0.1.0/PKG-INFO +263 -0
- piighost-0.1.0/README.md +231 -0
- piighost-0.1.0/SECURITY.md +32 -0
- piighost-0.1.0/docs/en/architecture.md +210 -0
- piighost-0.1.0/docs/en/examples/basic.md +189 -0
- piighost-0.1.0/docs/en/examples/langchain.md +271 -0
- piighost-0.1.0/docs/en/extending.md +384 -0
- piighost-0.1.0/docs/en/getting-started.md +155 -0
- piighost-0.1.0/docs/en/index.md +76 -0
- piighost-0.1.0/docs/en/reference/anonymizer.md +256 -0
- piighost-0.1.0/docs/en/reference/middleware.md +192 -0
- piighost-0.1.0/docs/en/reference/pipeline.md +178 -0
- piighost-0.1.0/docs/fr/architecture.md +210 -0
- piighost-0.1.0/docs/fr/examples/basic.md +189 -0
- piighost-0.1.0/docs/fr/examples/langchain.md +272 -0
- piighost-0.1.0/docs/fr/extending.md +386 -0
- piighost-0.1.0/docs/fr/getting-started.md +155 -0
- piighost-0.1.0/docs/fr/index.md +76 -0
- piighost-0.1.0/docs/fr/reference/anonymizer.md +256 -0
- piighost-0.1.0/docs/fr/reference/middleware.md +192 -0
- piighost-0.1.0/docs/fr/reference/pipeline.md +178 -0
- piighost-0.1.0/examples/graph/.env.example +72 -0
- piighost-0.1.0/examples/graph/.python-version +1 -0
- piighost-0.1.0/examples/graph/Dockerfile +51 -0
- piighost-0.1.0/examples/graph/README.md +87 -0
- piighost-0.1.0/examples/graph/aegra.json +19 -0
- piighost-0.1.0/examples/graph/docker-compose.yml +50 -0
- piighost-0.1.0/examples/graph/front/.codespellignore +1 -0
- piighost-0.1.0/examples/graph/front/.dockerignore +4 -0
- piighost-0.1.0/examples/graph/front/.env.example +13 -0
- piighost-0.1.0/examples/graph/front/.github/dependabot.yml +37 -0
- piighost-0.1.0/examples/graph/front/.github/workflows/ci.yml +77 -0
- piighost-0.1.0/examples/graph/front/.gitignore +30 -0
- piighost-0.1.0/examples/graph/front/.prettierignore +6 -0
- piighost-0.1.0/examples/graph/front/LICENSE +21 -0
- piighost-0.1.0/examples/graph/front/README.md +242 -0
- piighost-0.1.0/examples/graph/front/components.json +21 -0
- piighost-0.1.0/examples/graph/front/eslint.config.js +33 -0
- piighost-0.1.0/examples/graph/front/next.config.mjs +10 -0
- piighost-0.1.0/examples/graph/front/package.json +99 -0
- piighost-0.1.0/examples/graph/front/pnpm-lock.yaml +7576 -0
- piighost-0.1.0/examples/graph/front/postcss.config.mjs +5 -0
- piighost-0.1.0/examples/graph/front/prettier.config.js +11 -0
- piighost-0.1.0/examples/graph/front/public/logo.svg +8 -0
- piighost-0.1.0/examples/graph/front/src/app/api/[..._path]/route.ts +11 -0
- piighost-0.1.0/examples/graph/front/src/app/favicon.ico +0 -0
- piighost-0.1.0/examples/graph/front/src/app/globals.css +151 -0
- piighost-0.1.0/examples/graph/front/src/app/layout.tsx +30 -0
- piighost-0.1.0/examples/graph/front/src/app/page.tsx +23 -0
- piighost-0.1.0/examples/graph/front/src/components/icons/github.tsx +12 -0
- piighost-0.1.0/examples/graph/front/src/components/icons/langgraph.tsx +27 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/ContentBlocksPreview.tsx +37 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/MultimodalPreview.tsx +115 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/components/inbox-item-input.tsx +499 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/components/state-view.tsx +301 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/components/thread-actions-view.tsx +449 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/components/thread-id.tsx +84 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/components/tool-call-table.tsx +51 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/hooks/use-interrupted-actions.tsx +240 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/index.tsx +104 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/types.ts +104 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/utils.ts +235 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/artifact.tsx +189 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/history/index.tsx +146 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/index.tsx +567 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/markdown-styles.css +45 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/markdown-text.tsx +260 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/messages/ai.tsx +229 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/messages/generic-interrupt.tsx +160 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/messages/human.tsx +151 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/messages/shared.tsx +221 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/messages/tool-calls.tsx +191 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/syntax-highlighter.tsx +40 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/tooltip-icon-button.tsx +44 -0
- piighost-0.1.0/examples/graph/front/src/components/thread/utils.ts +15 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/avatar.tsx +51 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/button.tsx +61 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/card.tsx +75 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/input.tsx +20 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/label.tsx +22 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/password-input.tsx +60 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/separator.tsx +26 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/sheet.tsx +157 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/skeleton.tsx +13 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/sonner.tsx +27 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/switch.tsx +29 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/textarea.tsx +18 -0
- piighost-0.1.0/examples/graph/front/src/components/ui/tooltip.tsx +67 -0
- piighost-0.1.0/examples/graph/front/src/hooks/use-file-upload.tsx +270 -0
- piighost-0.1.0/examples/graph/front/src/hooks/useMediaQuery.tsx +16 -0
- piighost-0.1.0/examples/graph/front/src/providers/Stream.tsx +286 -0
- piighost-0.1.0/examples/graph/front/src/providers/Thread.tsx +75 -0
- piighost-0.1.0/examples/graph/front/src/providers/client.ts +8 -0
- piighost-0.1.0/examples/graph/front/tailwind.config.js +65 -0
- piighost-0.1.0/examples/graph/front/tsconfig.json +34 -0
- piighost-0.1.0/examples/graph/pyproject.toml +29 -0
- piighost-0.1.0/examples/graph/src/graph/__init__.py +2 -0
- piighost-0.1.0/examples/graph/src/graph/app.py +134 -0
- piighost-0.1.0/examples/graph/src/graph/graph.py +76 -0
- piighost-0.1.0/examples/graph/src/graph/py.typed +0 -0
- piighost-0.1.0/examples/graph/src/graph/ttl_sweeper.py +141 -0
- piighost-0.1.0/pyproject.toml +76 -0
- piighost-0.1.0/src/piighost/__init__.py +1 -0
- piighost-0.1.0/src/piighost/anonymizer/__init__.py +25 -0
- piighost-0.1.0/src/piighost/anonymizer/anonymizer.py +137 -0
- piighost-0.1.0/src/piighost/anonymizer/detector.py +207 -0
- piighost-0.1.0/src/piighost/anonymizer/models.py +59 -0
- piighost-0.1.0/src/piighost/anonymizer/occurrence.py +64 -0
- piighost-0.1.0/src/piighost/anonymizer/placeholder.py +160 -0
- piighost-0.1.0/src/piighost/middleware.py +202 -0
- piighost-0.1.0/src/piighost/pipeline.py +231 -0
- piighost-0.1.0/src/piighost/span_replacer/__init__.py +13 -0
- piighost-0.1.0/src/piighost/span_replacer/models.py +48 -0
- piighost-0.1.0/src/piighost/span_replacer/replacer.py +93 -0
- piighost-0.1.0/src/piighost/span_replacer/validator.py +64 -0
- piighost-0.1.0/tests/__init__.py +0 -0
- piighost-0.1.0/tests/test_anonymizer.py +397 -0
- piighost-0.1.0/tests/test_middleware.py +21 -0
- piighost-0.1.0/tests/test_span_replacer.py +186 -0
- piighost-0.1.0/uv.lock +2676 -0
- piighost-0.1.0/zensical.fr.toml +63 -0
- piighost-0.1.0/zensical.toml +62 -0
piighost-0.1.0/.cz.toml
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: Report a bug or unexpected behavior
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for taking the time to report a bug! Please fill in as much detail as possible.
|
|
9
|
+
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: description
|
|
12
|
+
attributes:
|
|
13
|
+
label: Description
|
|
14
|
+
description: A clear and concise description of what the bug is.
|
|
15
|
+
validations:
|
|
16
|
+
required: true
|
|
17
|
+
|
|
18
|
+
- type: textarea
|
|
19
|
+
id: reproduce
|
|
20
|
+
attributes:
|
|
21
|
+
label: Steps to Reproduce
|
|
22
|
+
description: Minimal code or steps to reproduce the behavior.
|
|
23
|
+
placeholder: |
|
|
24
|
+
```python
|
|
25
|
+
from piighost import ...
|
|
26
|
+
# your code here
|
|
27
|
+
```
|
|
28
|
+
validations:
|
|
29
|
+
required: true
|
|
30
|
+
|
|
31
|
+
- type: textarea
|
|
32
|
+
id: expected
|
|
33
|
+
attributes:
|
|
34
|
+
label: Expected Behavior
|
|
35
|
+
description: What did you expect to happen?
|
|
36
|
+
validations:
|
|
37
|
+
required: true
|
|
38
|
+
|
|
39
|
+
- type: textarea
|
|
40
|
+
id: actual
|
|
41
|
+
attributes:
|
|
42
|
+
label: Actual Behavior
|
|
43
|
+
description: What actually happened? Include the full traceback if applicable.
|
|
44
|
+
validations:
|
|
45
|
+
required: true
|
|
46
|
+
|
|
47
|
+
- type: input
|
|
48
|
+
id: version
|
|
49
|
+
attributes:
|
|
50
|
+
label: PIIGhost Version
|
|
51
|
+
placeholder: "e.g. 0.1.0"
|
|
52
|
+
validations:
|
|
53
|
+
required: true
|
|
54
|
+
|
|
55
|
+
- type: input
|
|
56
|
+
id: python
|
|
57
|
+
attributes:
|
|
58
|
+
label: Python Version
|
|
59
|
+
placeholder: "e.g. 3.12.3"
|
|
60
|
+
validations:
|
|
61
|
+
required: true
|
|
62
|
+
|
|
63
|
+
- type: textarea
|
|
64
|
+
id: context
|
|
65
|
+
attributes:
|
|
66
|
+
label: Additional Context
|
|
67
|
+
description: Any other context, environment details, or screenshots.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest a new feature or improvement
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for suggesting an improvement to PIIGhost!
|
|
9
|
+
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: problem
|
|
12
|
+
attributes:
|
|
13
|
+
label: Problem or Motivation
|
|
14
|
+
description: Is your feature request related to a problem? Describe the context.
|
|
15
|
+
placeholder: "e.g. I'm always frustrated when I try to use a spaCy detector instead of GLiNER2..."
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: solution
|
|
21
|
+
attributes:
|
|
22
|
+
label: Proposed Solution
|
|
23
|
+
description: A clear description of what you'd like to happen.
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
26
|
+
|
|
27
|
+
- type: textarea
|
|
28
|
+
id: alternatives
|
|
29
|
+
attributes:
|
|
30
|
+
label: Alternatives Considered
|
|
31
|
+
description: Any alternative approaches or workarounds you've considered.
|
|
32
|
+
|
|
33
|
+
- type: textarea
|
|
34
|
+
id: context
|
|
35
|
+
attributes:
|
|
36
|
+
label: Additional Context
|
|
37
|
+
description: Any other context, examples, or references.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What does this PR do? Why? -->
|
|
4
|
+
|
|
5
|
+
## Changes
|
|
6
|
+
|
|
7
|
+
<!-- Bullet list of the key changes -->
|
|
8
|
+
|
|
9
|
+
## Checklist
|
|
10
|
+
|
|
11
|
+
- [ ] `make lint` passes (ruff format, ruff check, pyrefly)
|
|
12
|
+
- [ ] `uv run pytest` passes
|
|
13
|
+
- [ ] New tests added for new functionality
|
|
14
|
+
- [ ] Documentation updated if the public API changed
|
|
15
|
+
- [ ] Commit messages follow [Conventional Commits](https://www.conventionalcommits.org/)
|
|
16
|
+
|
|
17
|
+
## Related Issues
|
|
18
|
+
|
|
19
|
+
<!-- Closes #123 -->
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
pull_request:
|
|
6
|
+
branches: [master]
|
|
7
|
+
push:
|
|
8
|
+
branches: [master]
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
lint:
|
|
15
|
+
name: Lint / Format / Type-check
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- uses: astral-sh/setup-uv@v6
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.13"
|
|
22
|
+
- uses: actions/cache@v4
|
|
23
|
+
with:
|
|
24
|
+
path: ~/.cache/uv
|
|
25
|
+
key: ${{ runner.os }}-uv-3.13-${{ hashFiles('uv.lock') }}
|
|
26
|
+
restore-keys: |
|
|
27
|
+
${{ runner.os }}-uv-3.13-
|
|
28
|
+
# Sync full workspace (3.13 required by examples/graph) for lint
|
|
29
|
+
- run: uv sync --locked --dev --no-progress -q
|
|
30
|
+
- run: make lint
|
|
31
|
+
|
|
32
|
+
tests:
|
|
33
|
+
name: Tests (Python ${{ matrix.python-version }})
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
needs: lint
|
|
36
|
+
strategy:
|
|
37
|
+
matrix:
|
|
38
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
39
|
+
fail-fast: false
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/checkout@v4
|
|
42
|
+
- uses: astral-sh/setup-uv@v6
|
|
43
|
+
with:
|
|
44
|
+
python-version: ${{ matrix.python-version }}
|
|
45
|
+
- uses: actions/cache@v4
|
|
46
|
+
with:
|
|
47
|
+
path: ~/.cache/uv
|
|
48
|
+
key: ${{ runner.os }}-uv-${{ matrix.python-version }}-${{ hashFiles('uv.lock') }}
|
|
49
|
+
restore-keys: |
|
|
50
|
+
${{ runner.os }}-uv-${{ matrix.python-version }}-
|
|
51
|
+
- run: uv sync --locked --dev --no-progress -q
|
|
52
|
+
- run: uv run pytest
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
pages: write
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
deploy:
|
|
15
|
+
environment:
|
|
16
|
+
name: github-pages
|
|
17
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/configure-pages@v5
|
|
21
|
+
with:
|
|
22
|
+
enablement: true
|
|
23
|
+
- uses: actions/checkout@v5
|
|
24
|
+
- uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: "3.12"
|
|
27
|
+
- run: pip install zensical
|
|
28
|
+
- run: zensical build --clean
|
|
29
|
+
- run: zensical build -f zensical.fr.toml
|
|
30
|
+
- uses: actions/upload-pages-artifact@v4
|
|
31
|
+
with:
|
|
32
|
+
path: site
|
|
33
|
+
- uses: actions/deploy-pages@v4
|
|
34
|
+
id: deployment
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
ci:
|
|
14
|
+
name: CI Checks
|
|
15
|
+
uses: ./.github/workflows/ci.yml
|
|
16
|
+
|
|
17
|
+
publish:
|
|
18
|
+
name: Publish to PyPI & GitHub Release
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
needs: ci
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
with:
|
|
24
|
+
fetch-depth: 0
|
|
25
|
+
- uses: astral-sh/setup-uv@v6
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.13"
|
|
28
|
+
- run: uv sync --locked --dev --no-progress -q
|
|
29
|
+
- run: uv build
|
|
30
|
+
- run: uv publish --verbose
|
|
31
|
+
- uses: softprops/action-gh-release@v2
|
|
32
|
+
with:
|
|
33
|
+
tag_name: ${{ github.ref_name }}
|
|
34
|
+
name: ${{ github.ref_name }}
|
|
35
|
+
generate_release_notes: true
|
|
36
|
+
files: |
|
|
37
|
+
dist/*.whl
|
|
38
|
+
dist/*.tar.gz
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
### Python template
|
|
2
|
+
# Byte-compiled / optimized / DLL files
|
|
3
|
+
__pycache__/
|
|
4
|
+
*.py[cod]
|
|
5
|
+
*$py.class
|
|
6
|
+
|
|
7
|
+
# C extensions
|
|
8
|
+
*.so
|
|
9
|
+
|
|
10
|
+
# Distribution / packaging
|
|
11
|
+
.Python
|
|
12
|
+
build/
|
|
13
|
+
develop-eggs/
|
|
14
|
+
dist/
|
|
15
|
+
downloads/
|
|
16
|
+
eggs/
|
|
17
|
+
.eggs/
|
|
18
|
+
lib/
|
|
19
|
+
lib64/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
wheels/
|
|
24
|
+
share/python-wheels/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
.installed.cfg
|
|
27
|
+
*.egg
|
|
28
|
+
MANIFEST
|
|
29
|
+
|
|
30
|
+
# PyInstaller
|
|
31
|
+
# Usually these files are written by a python script from a template
|
|
32
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
33
|
+
*.manifest
|
|
34
|
+
*.spec
|
|
35
|
+
|
|
36
|
+
# Installer logs
|
|
37
|
+
pip-log.txt
|
|
38
|
+
pip-delete-this-directory.txt
|
|
39
|
+
|
|
40
|
+
# Unit test / coverage reports
|
|
41
|
+
htmlcov/
|
|
42
|
+
.tox/
|
|
43
|
+
.nox/
|
|
44
|
+
.coverage
|
|
45
|
+
.coverage.*
|
|
46
|
+
.cache
|
|
47
|
+
nosetests.xml
|
|
48
|
+
coverage.xml
|
|
49
|
+
*.cover
|
|
50
|
+
*.py,cover
|
|
51
|
+
.hypothesis/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
cover/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
.pybuilder/
|
|
77
|
+
target/
|
|
78
|
+
|
|
79
|
+
# Jupyter Notebook
|
|
80
|
+
.ipynb_checkpoints
|
|
81
|
+
|
|
82
|
+
# IPython
|
|
83
|
+
profile_default/
|
|
84
|
+
ipython_config.py
|
|
85
|
+
|
|
86
|
+
# pyenv
|
|
87
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
88
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
89
|
+
# .python-version
|
|
90
|
+
|
|
91
|
+
# pipenv
|
|
92
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
93
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
94
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
95
|
+
# install all needed dependencies.
|
|
96
|
+
#Pipfile.lock
|
|
97
|
+
|
|
98
|
+
# poetry
|
|
99
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
100
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
101
|
+
# commonly ignored for libraries.
|
|
102
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
103
|
+
#poetry.lock
|
|
104
|
+
|
|
105
|
+
# pdm
|
|
106
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
107
|
+
#pdm.lock
|
|
108
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
109
|
+
# in version control.
|
|
110
|
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
111
|
+
.pdm.toml
|
|
112
|
+
.pdm-python
|
|
113
|
+
.pdm-build/
|
|
114
|
+
|
|
115
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
116
|
+
__pypackages__/
|
|
117
|
+
|
|
118
|
+
# Celery stuff
|
|
119
|
+
celerybeat-schedule
|
|
120
|
+
celerybeat.pid
|
|
121
|
+
|
|
122
|
+
# SageMath parsed files
|
|
123
|
+
*.sage.py
|
|
124
|
+
|
|
125
|
+
# Environments
|
|
126
|
+
.env
|
|
127
|
+
.venv
|
|
128
|
+
env/
|
|
129
|
+
venv/
|
|
130
|
+
ENV/
|
|
131
|
+
env.bak/
|
|
132
|
+
venv.bak/
|
|
133
|
+
|
|
134
|
+
# Spyder project settings
|
|
135
|
+
.spyderproject
|
|
136
|
+
.spyproject
|
|
137
|
+
|
|
138
|
+
# Rope project settings
|
|
139
|
+
.ropeproject
|
|
140
|
+
|
|
141
|
+
# mkdocs documentation
|
|
142
|
+
/site
|
|
143
|
+
|
|
144
|
+
# mypy
|
|
145
|
+
.mypy_cache/
|
|
146
|
+
.dmypy.json
|
|
147
|
+
dmypy.json
|
|
148
|
+
|
|
149
|
+
# Pyre type checker
|
|
150
|
+
.pyre/
|
|
151
|
+
|
|
152
|
+
# pytype static type analyzer
|
|
153
|
+
.pytype/
|
|
154
|
+
|
|
155
|
+
# Cython debug symbols
|
|
156
|
+
cython_debug/
|
|
157
|
+
|
|
158
|
+
# PyCharm
|
|
159
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
160
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
161
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
162
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
163
|
+
.idea/
|
|
164
|
+
|
|
165
|
+
# Virtual environments
|
|
166
|
+
.venv/
|
|
167
|
+
|
|
168
|
+
# IDE
|
|
169
|
+
.vscode/
|
|
170
|
+
*.swp
|
|
171
|
+
*.swo
|
|
172
|
+
# OS
|
|
173
|
+
.DS_Store
|
|
174
|
+
Thumbs.db
|
|
175
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2025-03-22
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
- **anonymizer**: 4-stage pipeline (Detect → Expand → Map → Replace) with protocol-based dependency injection
|
|
13
|
+
- **detector**: `GlinerDetector` using GLiNER2 NER for entity detection
|
|
14
|
+
- **occurrence-finder**: `RegexOccurrenceFinder` for word-boundary regex matching of all entity occurrences
|
|
15
|
+
- **placeholder-factory**: `CounterPlaceholderFactory` for stable `<<LABEL_N>>` tags
|
|
16
|
+
- **span-replacer**: `SpanReplacer` with reverse spans for reliable deanonymization
|
|
17
|
+
- **pipeline**: `AnonymizationPipeline` with `PlaceholderStore` protocol for cross-session caching (SHA-256 keyed)
|
|
18
|
+
- **middleware**: `PIIAnonymizationMiddleware` for LangChain/LangGraph — hooks on `abefore_model`, `aafter_model`, `awrap_tool_call`
|
|
19
|
+
- **pipeline**: `deanonymize_value` for per-argument placeholder resolution
|
|
20
|
+
- **examples**: LangGraph + FastAPI example with React frontend and Aegra integration
|
piighost-0.1.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
PIIGhost is a PII anonymization system for AI agent conversations. It transparently intercepts LLM interactions to detect, anonymize, and deanonymize sensitive entities (names, locations, etc.) using GLiNER2 NER, integrated via LangChain middleware into a LangGraph agent. Built on Aegra (self-hosted LangSmith alternative).
|
|
8
|
+
|
|
9
|
+
## Development Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
uv sync # Install dependencies
|
|
13
|
+
uv run aegra dev # Start dev server (graph + FastAPI on port 8000)
|
|
14
|
+
make lint # Format (ruff), lint (ruff), type-check (pyrefly)
|
|
15
|
+
uv run pytest # Run all tests
|
|
16
|
+
uv run pytest tests/test_anonymizer.py -k "test_name" # Run a single test
|
|
17
|
+
docker compose up postgres -d # PostgreSQL only
|
|
18
|
+
docker compose up --build # Full stack (Postgres + API)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Architecture
|
|
22
|
+
|
|
23
|
+
### 4-Stage Anonymization Pipeline
|
|
24
|
+
|
|
25
|
+
`Anonymizer` (`anonymizer/anonymizer.py`) orchestrates: **Detect → Expand → Map → Replace**
|
|
26
|
+
|
|
27
|
+
1. **Detect**: `EntityDetector` protocol — `GlinerDetector` runs GLiNER2 NER to find entities
|
|
28
|
+
2. **Expand**: `OccurrenceFinder` protocol — `RegexOccurrenceFinder` locates all occurrences via word-boundary regex
|
|
29
|
+
3. **Map**: `PlaceholderFactory` protocol — `CounterPlaceholderFactory` assigns stable tags (`<<PERSON_1>>`)
|
|
30
|
+
4. **Replace**: `SpanReplacer` applies character-position substitutions with reverse spans for deanonymization
|
|
31
|
+
|
|
32
|
+
### Session Layer
|
|
33
|
+
|
|
34
|
+
`AnonymizationPipeline` (`pipeline.py`) wraps the stateless `Anonymizer` with:
|
|
35
|
+
- `PlaceholderStore` protocol — async persistent cache (SHA-256 keyed) for cross-session placeholder reuse
|
|
36
|
+
- In-memory registry for fast bidirectional lookup within a session
|
|
37
|
+
|
|
38
|
+
### Middleware Integration
|
|
39
|
+
|
|
40
|
+
`PIIAnonymizationMiddleware` (`middleware.py`) extends LangChain's `AgentMiddleware`:
|
|
41
|
+
- `abefore_model` — anonymizes all messages before the LLM sees them (NER on human messages, string-replace on AI/tool)
|
|
42
|
+
- `aafter_model` — deanonymizes for user display
|
|
43
|
+
- `awrap_tool_call` — deanonymizes tool args, executes tool, re-anonymizes result
|
|
44
|
+
|
|
45
|
+
### Entry Points
|
|
46
|
+
|
|
47
|
+
- **LangGraph agent**: `graph.py:graph` — agent with tools (`send_email`, `get_weather`) and PII middleware
|
|
48
|
+
- **FastAPI app**: `app.py:app` — HTTP server with Keyshield API key auth and TTL sweeper background task
|
|
49
|
+
- **Config**: `aegra.json` binds both together for `aegra dev`
|
|
50
|
+
|
|
51
|
+
### Design Patterns
|
|
52
|
+
|
|
53
|
+
All pipeline stages use **protocols** (structural subtyping) for dependency injection, making components swappable and testable. Tests use `FakeDetector` to avoid loading the real GLiNER2 model.
|
|
54
|
+
|
|
55
|
+
## Conventions
|
|
56
|
+
|
|
57
|
+
- **Commits**: Conventional Commits via Commitizen (`feat:`, `fix:`, `refactor:`, etc.)
|
|
58
|
+
- **Type checking**: PyReFly (not mypy)
|
|
59
|
+
- **Formatting/linting**: Ruff
|
|
60
|
+
- **Package manager**: uv (not pip)
|
|
61
|
+
- **Python**: 3.12+
|
|
62
|
+
- **Data models**: Frozen dataclasses for immutability (`Entity`, `Placeholder`, `Span`, etc.)
|
|
63
|
+
|
|
64
|
+
## Environment Setup
|
|
65
|
+
|
|
66
|
+
Copy `.env.example` to `.env`. Key variables:
|
|
67
|
+
- `OPENAI_API_KEY` (or `ANTHROPIC_API_KEY`) — required for LLM
|
|
68
|
+
- `AEGRA_CONFIG=aegra.json` — mandatory
|
|
69
|
+
- Database: PostgreSQL connection fields or `DATABASE_URL`
|
|
70
|
+
- Observability: `OTEL_TARGETS` for Langfuse/Phoenix/OTLP tracing
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Commitment
|
|
4
|
+
|
|
5
|
+
The PIIGhost team and community welcomes contributors worldwide who share our mission of making PII protection accessible and composable. We are committed to maintaining an inclusive, respectful environment for all participants.
|
|
6
|
+
|
|
7
|
+
## Scope
|
|
8
|
+
|
|
9
|
+
This code of conduct applies to all spaces managed by the PIIGhost project, including:
|
|
10
|
+
- GitHub issues, pull requests, and discussions
|
|
11
|
+
- Community events and meetups
|
|
12
|
+
- Any other communication forums related to the project
|
|
13
|
+
|
|
14
|
+
## Our Standards
|
|
15
|
+
|
|
16
|
+
We ask all community members to:
|
|
17
|
+
|
|
18
|
+
### Be Friendly and Patient
|
|
19
|
+
|
|
20
|
+
Foster a welcoming atmosphere for everyone, regardless of experience level.
|
|
21
|
+
|
|
22
|
+
### Be Welcoming
|
|
23
|
+
|
|
24
|
+
To people of all backgrounds, identities, cultures, national origins, educational levels, sexual orientations, gender identities, ages, abilities, religions, and beliefs.
|
|
25
|
+
|
|
26
|
+
### Be Considerate
|
|
27
|
+
|
|
28
|
+
Our community spans the globe with varied primary languages. Your work and words affect others globally — be mindful of that.
|
|
29
|
+
|
|
30
|
+
### Be Respectful
|
|
31
|
+
|
|
32
|
+
Disagreements are natural and healthy. Disagreement does not justify poor behavior or personal attacks. Critique ideas, not people.
|
|
33
|
+
|
|
34
|
+
### Choose Your Words Carefully
|
|
35
|
+
|
|
36
|
+
We are a professional community. The following are not acceptable:
|
|
37
|
+
- Violent threats or language
|
|
38
|
+
- Discriminatory jokes or language
|
|
39
|
+
- Sexual or violent content
|
|
40
|
+
- Doxing or sharing private information
|
|
41
|
+
- Personal insults
|
|
42
|
+
- Unwelcome sexual attention
|
|
43
|
+
- Harassment of any kind
|
|
44
|
+
|
|
45
|
+
## Reporting Violations
|
|
46
|
+
|
|
47
|
+
If you witness a violation of this code of conduct, please report it **privately** by opening a confidential report via [GitHub's private vulnerability reporting](https://github.com/Athroniaeth/piighost/security/advisories/new) or by contacting the maintainer directly.
|
|
48
|
+
|
|
49
|
+
Include:
|
|
50
|
+
- Description of the violation
|
|
51
|
+
- Date and location (link, comment, etc.)
|
|
52
|
+
- Any relevant evidence
|
|
53
|
+
|
|
54
|
+
## Consequences
|
|
55
|
+
|
|
56
|
+
Violations may result in:
|
|
57
|
+
- Warning from maintainers
|
|
58
|
+
- Temporary suspension from community participation
|
|
59
|
+
- Permanent removal from the project
|
|
60
|
+
|
|
61
|
+
The PIIGhost maintainers will review all reports and take appropriate action.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
*Inspired by the Speak Up! project and the Contributor Covenant.*
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Contributing to PIIGhost
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to PIIGhost! We welcome contributions from everyone.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Python 3.12+
|
|
8
|
+
- [`uv`](https://docs.astral.sh/uv/) package manager
|
|
9
|
+
- Git and a GitHub account
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
1. **Fork the repository** on GitHub
|
|
14
|
+
2. **Clone your fork** locally:
|
|
15
|
+
```bash
|
|
16
|
+
git clone https://github.com/YOUR-USERNAME/piighost.git
|
|
17
|
+
cd piighost
|
|
18
|
+
```
|
|
19
|
+
3. **Add upstream remote** for syncing:
|
|
20
|
+
```bash
|
|
21
|
+
git remote add upstream https://github.com/Athroniaeth/piighost.git
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Development Workflow
|
|
25
|
+
|
|
26
|
+
### 1. Create a Feature Branch
|
|
27
|
+
|
|
28
|
+
Always branch from `master`:
|
|
29
|
+
```bash
|
|
30
|
+
git checkout -b feature/your-feature-name
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Install Dependencies
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uv sync
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 3. Make Your Changes
|
|
40
|
+
|
|
41
|
+
Follow the existing code style and patterns. Key conventions:
|
|
42
|
+
- **Protocols** for every pipeline stage — keep components swappable
|
|
43
|
+
- **Frozen dataclasses** for data models (`Entity`, `Placeholder`, `Span`, etc.)
|
|
44
|
+
- **`FakeDetector`** in tests — never load the real GLiNER2 model in CI
|
|
45
|
+
|
|
46
|
+
### 4. Quality Assurance
|
|
47
|
+
|
|
48
|
+
Run all checks before submitting:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
make lint # Format (ruff), lint (ruff), type-check (pyrefly)
|
|
52
|
+
uv run pytest # Run tests
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 5. Commit Your Changes
|
|
56
|
+
|
|
57
|
+
Use [Conventional Commits](https://www.conventionalcommits.org/) via Commitizen:
|
|
58
|
+
```bash
|
|
59
|
+
cz commit
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Follow the prompts to select commit type (`feat`, `fix`, `docs`, `refactor`, etc.).
|
|
63
|
+
|
|
64
|
+
## Pull Request Guidelines
|
|
65
|
+
|
|
66
|
+
1. **Target the `master` branch**
|
|
67
|
+
2. **Ensure all checks pass**:
|
|
68
|
+
- `make lint` — no linting or type errors
|
|
69
|
+
- `uv run pytest` — all tests green
|
|
70
|
+
3. **Add tests** for any new functionality
|
|
71
|
+
4. **Update documentation** if the public API changes
|
|
72
|
+
5. **Sync with upstream** if your branch diverged:
|
|
73
|
+
```bash
|
|
74
|
+
git fetch upstream
|
|
75
|
+
git rebase upstream/master
|
|
76
|
+
git push --force-with-lease
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### PR Checklist
|
|
80
|
+
|
|
81
|
+
- [ ] Code follows project style guidelines
|
|
82
|
+
- [ ] Tests pass locally (`make lint && uv run pytest`)
|
|
83
|
+
- [ ] New tests added for new functionality
|
|
84
|
+
- [ ] Documentation updated if needed
|
|
85
|
+
- [ ] Synced with upstream master
|
|
86
|
+
|
|
87
|
+
## Adding a New Pipeline Stage
|
|
88
|
+
|
|
89
|
+
New detector, occurrence finder, or placeholder factory implementations must:
|
|
90
|
+
- Implement the corresponding **protocol** (`EntityDetector`, `OccurrenceFinder`, `PlaceholderFactory`, `SpanValidator`)
|
|
91
|
+
- Include tests that use the protocol interface (not the concrete class)
|
|
92
|
+
- Not load heavy ML models in test code — use `FakeDetector` or equivalents
|
|
93
|
+
|
|
94
|
+
## Questions?
|
|
95
|
+
|
|
96
|
+
Open a [GitHub Discussion](https://github.com/Athroniaeth/piighost/discussions) or an issue. We're happy to help!
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
Thank you for contributing to PIIGhost!
|