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.
Files changed (137) hide show
  1. piighost-0.1.0/.cz.toml +7 -0
  2. piighost-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +67 -0
  3. piighost-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +37 -0
  4. piighost-0.1.0/.github/pull_request_template.md +19 -0
  5. piighost-0.1.0/.github/workflows/ci.yml +52 -0
  6. piighost-0.1.0/.github/workflows/docs.yml +34 -0
  7. piighost-0.1.0/.github/workflows/release.yml +38 -0
  8. piighost-0.1.0/.gitignore +175 -0
  9. piighost-0.1.0/.python-version +1 -0
  10. piighost-0.1.0/CHANGELOG.md +20 -0
  11. piighost-0.1.0/CLAUDE.md +70 -0
  12. piighost-0.1.0/CODE_OF_CONDUCT.md +65 -0
  13. piighost-0.1.0/CONTRIBUTING.md +100 -0
  14. piighost-0.1.0/LICENSE +21 -0
  15. piighost-0.1.0/Makefile +16 -0
  16. piighost-0.1.0/PKG-INFO +263 -0
  17. piighost-0.1.0/README.md +231 -0
  18. piighost-0.1.0/SECURITY.md +32 -0
  19. piighost-0.1.0/docs/en/architecture.md +210 -0
  20. piighost-0.1.0/docs/en/examples/basic.md +189 -0
  21. piighost-0.1.0/docs/en/examples/langchain.md +271 -0
  22. piighost-0.1.0/docs/en/extending.md +384 -0
  23. piighost-0.1.0/docs/en/getting-started.md +155 -0
  24. piighost-0.1.0/docs/en/index.md +76 -0
  25. piighost-0.1.0/docs/en/reference/anonymizer.md +256 -0
  26. piighost-0.1.0/docs/en/reference/middleware.md +192 -0
  27. piighost-0.1.0/docs/en/reference/pipeline.md +178 -0
  28. piighost-0.1.0/docs/fr/architecture.md +210 -0
  29. piighost-0.1.0/docs/fr/examples/basic.md +189 -0
  30. piighost-0.1.0/docs/fr/examples/langchain.md +272 -0
  31. piighost-0.1.0/docs/fr/extending.md +386 -0
  32. piighost-0.1.0/docs/fr/getting-started.md +155 -0
  33. piighost-0.1.0/docs/fr/index.md +76 -0
  34. piighost-0.1.0/docs/fr/reference/anonymizer.md +256 -0
  35. piighost-0.1.0/docs/fr/reference/middleware.md +192 -0
  36. piighost-0.1.0/docs/fr/reference/pipeline.md +178 -0
  37. piighost-0.1.0/examples/graph/.env.example +72 -0
  38. piighost-0.1.0/examples/graph/.python-version +1 -0
  39. piighost-0.1.0/examples/graph/Dockerfile +51 -0
  40. piighost-0.1.0/examples/graph/README.md +87 -0
  41. piighost-0.1.0/examples/graph/aegra.json +19 -0
  42. piighost-0.1.0/examples/graph/docker-compose.yml +50 -0
  43. piighost-0.1.0/examples/graph/front/.codespellignore +1 -0
  44. piighost-0.1.0/examples/graph/front/.dockerignore +4 -0
  45. piighost-0.1.0/examples/graph/front/.env.example +13 -0
  46. piighost-0.1.0/examples/graph/front/.github/dependabot.yml +37 -0
  47. piighost-0.1.0/examples/graph/front/.github/workflows/ci.yml +77 -0
  48. piighost-0.1.0/examples/graph/front/.gitignore +30 -0
  49. piighost-0.1.0/examples/graph/front/.prettierignore +6 -0
  50. piighost-0.1.0/examples/graph/front/LICENSE +21 -0
  51. piighost-0.1.0/examples/graph/front/README.md +242 -0
  52. piighost-0.1.0/examples/graph/front/components.json +21 -0
  53. piighost-0.1.0/examples/graph/front/eslint.config.js +33 -0
  54. piighost-0.1.0/examples/graph/front/next.config.mjs +10 -0
  55. piighost-0.1.0/examples/graph/front/package.json +99 -0
  56. piighost-0.1.0/examples/graph/front/pnpm-lock.yaml +7576 -0
  57. piighost-0.1.0/examples/graph/front/postcss.config.mjs +5 -0
  58. piighost-0.1.0/examples/graph/front/prettier.config.js +11 -0
  59. piighost-0.1.0/examples/graph/front/public/logo.svg +8 -0
  60. piighost-0.1.0/examples/graph/front/src/app/api/[..._path]/route.ts +11 -0
  61. piighost-0.1.0/examples/graph/front/src/app/favicon.ico +0 -0
  62. piighost-0.1.0/examples/graph/front/src/app/globals.css +151 -0
  63. piighost-0.1.0/examples/graph/front/src/app/layout.tsx +30 -0
  64. piighost-0.1.0/examples/graph/front/src/app/page.tsx +23 -0
  65. piighost-0.1.0/examples/graph/front/src/components/icons/github.tsx +12 -0
  66. piighost-0.1.0/examples/graph/front/src/components/icons/langgraph.tsx +27 -0
  67. piighost-0.1.0/examples/graph/front/src/components/thread/ContentBlocksPreview.tsx +37 -0
  68. piighost-0.1.0/examples/graph/front/src/components/thread/MultimodalPreview.tsx +115 -0
  69. piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/components/inbox-item-input.tsx +499 -0
  70. piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/components/state-view.tsx +301 -0
  71. piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/components/thread-actions-view.tsx +449 -0
  72. piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/components/thread-id.tsx +84 -0
  73. piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/components/tool-call-table.tsx +51 -0
  74. piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/hooks/use-interrupted-actions.tsx +240 -0
  75. piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/index.tsx +104 -0
  76. piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/types.ts +104 -0
  77. piighost-0.1.0/examples/graph/front/src/components/thread/agent-inbox/utils.ts +235 -0
  78. piighost-0.1.0/examples/graph/front/src/components/thread/artifact.tsx +189 -0
  79. piighost-0.1.0/examples/graph/front/src/components/thread/history/index.tsx +146 -0
  80. piighost-0.1.0/examples/graph/front/src/components/thread/index.tsx +567 -0
  81. piighost-0.1.0/examples/graph/front/src/components/thread/markdown-styles.css +45 -0
  82. piighost-0.1.0/examples/graph/front/src/components/thread/markdown-text.tsx +260 -0
  83. piighost-0.1.0/examples/graph/front/src/components/thread/messages/ai.tsx +229 -0
  84. piighost-0.1.0/examples/graph/front/src/components/thread/messages/generic-interrupt.tsx +160 -0
  85. piighost-0.1.0/examples/graph/front/src/components/thread/messages/human.tsx +151 -0
  86. piighost-0.1.0/examples/graph/front/src/components/thread/messages/shared.tsx +221 -0
  87. piighost-0.1.0/examples/graph/front/src/components/thread/messages/tool-calls.tsx +191 -0
  88. piighost-0.1.0/examples/graph/front/src/components/thread/syntax-highlighter.tsx +40 -0
  89. piighost-0.1.0/examples/graph/front/src/components/thread/tooltip-icon-button.tsx +44 -0
  90. piighost-0.1.0/examples/graph/front/src/components/thread/utils.ts +15 -0
  91. piighost-0.1.0/examples/graph/front/src/components/ui/avatar.tsx +51 -0
  92. piighost-0.1.0/examples/graph/front/src/components/ui/button.tsx +61 -0
  93. piighost-0.1.0/examples/graph/front/src/components/ui/card.tsx +75 -0
  94. piighost-0.1.0/examples/graph/front/src/components/ui/input.tsx +20 -0
  95. piighost-0.1.0/examples/graph/front/src/components/ui/label.tsx +22 -0
  96. piighost-0.1.0/examples/graph/front/src/components/ui/password-input.tsx +60 -0
  97. piighost-0.1.0/examples/graph/front/src/components/ui/separator.tsx +26 -0
  98. piighost-0.1.0/examples/graph/front/src/components/ui/sheet.tsx +157 -0
  99. piighost-0.1.0/examples/graph/front/src/components/ui/skeleton.tsx +13 -0
  100. piighost-0.1.0/examples/graph/front/src/components/ui/sonner.tsx +27 -0
  101. piighost-0.1.0/examples/graph/front/src/components/ui/switch.tsx +29 -0
  102. piighost-0.1.0/examples/graph/front/src/components/ui/textarea.tsx +18 -0
  103. piighost-0.1.0/examples/graph/front/src/components/ui/tooltip.tsx +67 -0
  104. piighost-0.1.0/examples/graph/front/src/hooks/use-file-upload.tsx +270 -0
  105. piighost-0.1.0/examples/graph/front/src/hooks/useMediaQuery.tsx +16 -0
  106. piighost-0.1.0/examples/graph/front/src/providers/Stream.tsx +286 -0
  107. piighost-0.1.0/examples/graph/front/src/providers/Thread.tsx +75 -0
  108. piighost-0.1.0/examples/graph/front/src/providers/client.ts +8 -0
  109. piighost-0.1.0/examples/graph/front/tailwind.config.js +65 -0
  110. piighost-0.1.0/examples/graph/front/tsconfig.json +34 -0
  111. piighost-0.1.0/examples/graph/pyproject.toml +29 -0
  112. piighost-0.1.0/examples/graph/src/graph/__init__.py +2 -0
  113. piighost-0.1.0/examples/graph/src/graph/app.py +134 -0
  114. piighost-0.1.0/examples/graph/src/graph/graph.py +76 -0
  115. piighost-0.1.0/examples/graph/src/graph/py.typed +0 -0
  116. piighost-0.1.0/examples/graph/src/graph/ttl_sweeper.py +141 -0
  117. piighost-0.1.0/pyproject.toml +76 -0
  118. piighost-0.1.0/src/piighost/__init__.py +1 -0
  119. piighost-0.1.0/src/piighost/anonymizer/__init__.py +25 -0
  120. piighost-0.1.0/src/piighost/anonymizer/anonymizer.py +137 -0
  121. piighost-0.1.0/src/piighost/anonymizer/detector.py +207 -0
  122. piighost-0.1.0/src/piighost/anonymizer/models.py +59 -0
  123. piighost-0.1.0/src/piighost/anonymizer/occurrence.py +64 -0
  124. piighost-0.1.0/src/piighost/anonymizer/placeholder.py +160 -0
  125. piighost-0.1.0/src/piighost/middleware.py +202 -0
  126. piighost-0.1.0/src/piighost/pipeline.py +231 -0
  127. piighost-0.1.0/src/piighost/span_replacer/__init__.py +13 -0
  128. piighost-0.1.0/src/piighost/span_replacer/models.py +48 -0
  129. piighost-0.1.0/src/piighost/span_replacer/replacer.py +93 -0
  130. piighost-0.1.0/src/piighost/span_replacer/validator.py +64 -0
  131. piighost-0.1.0/tests/__init__.py +0 -0
  132. piighost-0.1.0/tests/test_anonymizer.py +397 -0
  133. piighost-0.1.0/tests/test_middleware.py +21 -0
  134. piighost-0.1.0/tests/test_span_replacer.py +186 -0
  135. piighost-0.1.0/uv.lock +2676 -0
  136. piighost-0.1.0/zensical.fr.toml +63 -0
  137. piighost-0.1.0/zensical.toml +62 -0
@@ -0,0 +1,7 @@
1
+ [tool.commitizen]
2
+ name = "cz_conventional_commits"
3
+ tag_format = "$version"
4
+ version_scheme = "pep440"
5
+ version_provider = "uv"
6
+ update_changelog_on_bump = true
7
+ major_version_zero = true
@@ -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
@@ -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!