nextcloud-organizer-mcp 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.
- nextcloud_organizer_mcp-0.1.0/.env.example +96 -0
- nextcloud_organizer_mcp-0.1.0/.github/dependabot.yml +18 -0
- nextcloud_organizer_mcp-0.1.0/.github/workflows/ci.yml +37 -0
- nextcloud_organizer_mcp-0.1.0/.github/workflows/integration.yml +104 -0
- nextcloud_organizer_mcp-0.1.0/.github/workflows/release.yml +48 -0
- nextcloud_organizer_mcp-0.1.0/.gitignore +27 -0
- nextcloud_organizer_mcp-0.1.0/.pre-commit-config.yaml +25 -0
- nextcloud_organizer_mcp-0.1.0/CHANGELOG.md +664 -0
- nextcloud_organizer_mcp-0.1.0/CLAUDE.md +14 -0
- nextcloud_organizer_mcp-0.1.0/CONTRIBUTING.md +74 -0
- nextcloud_organizer_mcp-0.1.0/LICENSE +21 -0
- nextcloud_organizer_mcp-0.1.0/PKG-INFO +467 -0
- nextcloud_organizer_mcp-0.1.0/README.md +441 -0
- nextcloud_organizer_mcp-0.1.0/SECURITY.md +89 -0
- nextcloud_organizer_mcp-0.1.0/assets/logo-mark.png +0 -0
- nextcloud_organizer_mcp-0.1.0/assets/logo-mark.svg +7 -0
- nextcloud_organizer_mcp-0.1.0/assets/logo.png +0 -0
- nextcloud_organizer_mcp-0.1.0/assets/logo.svg +14 -0
- nextcloud_organizer_mcp-0.1.0/assets/social-preview.png +0 -0
- nextcloud_organizer_mcp-0.1.0/docs/architecture.md +155 -0
- nextcloud_organizer_mcp-0.1.0/docs/deployment.md +290 -0
- nextcloud_organizer_mcp-0.1.0/docs/tools.md +1901 -0
- nextcloud_organizer_mcp-0.1.0/pyproject.toml +122 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/__init__.py +3 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/admin.py +234 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/caldav_client.py +4272 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/config.py +251 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/errors.py +98 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/event_mapping.py +1365 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/mapping.py +2130 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/notes_client.py +218 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/notes_mapping.py +80 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/notes_sections.py +140 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/personal_auth.py +637 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/py.typed +0 -0
- nextcloud_organizer_mcp-0.1.0/src/nextcloud_organizer_mcp/server.py +2202 -0
- nextcloud_organizer_mcp-0.1.0/tests/conftest.py +168 -0
- nextcloud_organizer_mcp-0.1.0/tests/test_admin.py +266 -0
- nextcloud_organizer_mcp-0.1.0/tests/test_auth.py +437 -0
- nextcloud_organizer_mcp-0.1.0/tests/test_auth_lifecycle.py +367 -0
- nextcloud_organizer_mcp-0.1.0/tests/test_caldav_client.py +7486 -0
- nextcloud_organizer_mcp-0.1.0/tests/test_config.py +591 -0
- nextcloud_organizer_mcp-0.1.0/tests/test_event_mapping.py +2099 -0
- nextcloud_organizer_mcp-0.1.0/tests/test_integration.py +772 -0
- nextcloud_organizer_mcp-0.1.0/tests/test_mapping.py +2406 -0
- nextcloud_organizer_mcp-0.1.0/tests/test_notes_client.py +558 -0
- nextcloud_organizer_mcp-0.1.0/tests/test_notes_mapping.py +104 -0
- nextcloud_organizer_mcp-0.1.0/tests/test_notes_sections.py +195 -0
- nextcloud_organizer_mcp-0.1.0/tests/test_server.py +2064 -0
- nextcloud_organizer_mcp-0.1.0/uv.lock +2723 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Required. Base URL of your Nextcloud instance (no path), e.g. https://cloud.example.com.
|
|
2
|
+
# Used for the Notes app's REST API and as the base from which NEXTCLOUD_CALDAV_URL is
|
|
3
|
+
# derived when unset. Reuses NEXTCLOUD_USERNAME/NEXTCLOUD_APP_PASSWORD.
|
|
4
|
+
# Must be https:// - the server refuses to start with a http:// URL unless it
|
|
5
|
+
# points at a local address (localhost/127.0.0.1/::1) or
|
|
6
|
+
# NEXTCLOUD_ALLOW_INSECURE_HTTP=1 is set (see below), since http:// sends this
|
|
7
|
+
# app password in cleartext Basic Auth on every request.
|
|
8
|
+
NEXTCLOUD_BASE_URL=https://cloud.example.com
|
|
9
|
+
NEXTCLOUD_USERNAME=your-nextcloud-username
|
|
10
|
+
NEXTCLOUD_APP_PASSWORD=your-nextcloud-app-password
|
|
11
|
+
|
|
12
|
+
# Optional. DAV endpoint root. Defaults to <NEXTCLOUD_BASE_URL>/remote.php/dav/.
|
|
13
|
+
# Only needed when the DAV endpoint is not <base>/remote.php/dav/ (e.g. custom reverse
|
|
14
|
+
# proxy or different host). Both NEXTCLOUD_BASE_URL and NEXTCLOUD_CALDAV_URL must point
|
|
15
|
+
# at the same Nextcloud instance.
|
|
16
|
+
# NEXTCLOUD_CALDAV_URL=https://cloud.example.com/remote.php/dav/
|
|
17
|
+
|
|
18
|
+
# Optional. How long (in seconds) to wait for a CalDAV or Notes API HTTP
|
|
19
|
+
# request to Nextcloud before giving up. Without a timeout, a hung Nextcloud
|
|
20
|
+
# server would hang this server forever. Default: 30.
|
|
21
|
+
# NEXTCLOUD_HTTP_TIMEOUT_SECONDS=30
|
|
22
|
+
|
|
23
|
+
# Only needed if NEXTCLOUD_CALDAV_URL or NEXTCLOUD_BASE_URL above is genuinely
|
|
24
|
+
# http:// and does NOT point at localhost/127.0.0.1/::1 (e.g. an
|
|
25
|
+
# internal-network Nextcloud without its own TLS). WARNING: this sends your
|
|
26
|
+
# Nextcloud app password in cleartext on every request - do not set this for
|
|
27
|
+
# a real deployment.
|
|
28
|
+
# NEXTCLOUD_ALLOW_INSECURE_HTTP=1
|
|
29
|
+
|
|
30
|
+
# OAuth 2.1 authentication (PersonalAuthProvider). The server is a Claude
|
|
31
|
+
# custom connector, authenticated via OAuth + PKCE instead of a static token.
|
|
32
|
+
|
|
33
|
+
# Required. The exact public URL clients (Claude) use to reach this server -
|
|
34
|
+
# must match precisely, including scheme, or the OAuth discovery/redirect
|
|
35
|
+
# flow will fail. Locally this is http://127.0.0.1:8000; in production it's
|
|
36
|
+
# your public Tailscale Funnel HTTPS URL, e.g.
|
|
37
|
+
# https://your-host.your-tailnet.ts.net
|
|
38
|
+
PUBLIC_BASE_URL=http://127.0.0.1:8000
|
|
39
|
+
|
|
40
|
+
# Password gate on the OAuth /authorize step. Required (the server refuses
|
|
41
|
+
# to start without it) whenever PUBLIC_BASE_URL above is not localhost, or
|
|
42
|
+
# MCP_HOST below is bound to a non-local address (e.g. 0.0.0.0) - the
|
|
43
|
+
# redirect-domain allow-list alone does NOT stop a scripted client from
|
|
44
|
+
# registering itself via the (intentionally open) DCR endpoint and
|
|
45
|
+
# self-issuing a valid access token, since it never has to actually control
|
|
46
|
+
# the redirect domain, only claim one that's on the allow-list. This password
|
|
47
|
+
# is the only real gate once the server is reachable from the public
|
|
48
|
+
# internet (Tailscale Funnel). Not needed for local-only use
|
|
49
|
+
# (PUBLIC_BASE_URL=http://127.0.0.1:... or http://localhost:... AND
|
|
50
|
+
# MCP_HOST=127.0.0.1/localhost).
|
|
51
|
+
#
|
|
52
|
+
# Uncomment and set this to a long random secret for any non-localhost
|
|
53
|
+
# deployment - the server will refuse to start with the placeholder value
|
|
54
|
+
# below, and will also refuse to start with no password at all once it's
|
|
55
|
+
# reachable from anywhere but localhost. Generate a value with:
|
|
56
|
+
# python3 -c "import secrets; print(secrets.token_urlsafe(24))"
|
|
57
|
+
# MCP_OAUTH_PASSWORD=change-me-to-a-long-random-password
|
|
58
|
+
|
|
59
|
+
# Optional, comma-separated. Only these domains (and subdomains) may
|
|
60
|
+
# complete the OAuth redirect. Default when unset: claude.ai,claude.com for a
|
|
61
|
+
# non-localhost PUBLIC_BASE_URL (a "localhost" entry in a public deployment's
|
|
62
|
+
# allow-list can never be reached by a real OAuth redirect anyway); for a
|
|
63
|
+
# localhost PUBLIC_BASE_URL, claude.ai,claude.com,localhost.
|
|
64
|
+
# MCP_OAUTH_ALLOWED_REDIRECT_DOMAINS=claude.ai,claude.com,localhost
|
|
65
|
+
|
|
66
|
+
# Optional. How long issued access tokens are valid, in seconds.
|
|
67
|
+
# Default: 2592000 (30 days).
|
|
68
|
+
# MCP_OAUTH_ACCESS_TOKEN_EXPIRY_SECONDS=2592000
|
|
69
|
+
|
|
70
|
+
# Optional. How long issued refresh tokens are valid, in seconds, before a
|
|
71
|
+
# client must fully re-authorize (D5) - bounds how long a leaked
|
|
72
|
+
# oauth_tokens.json grants access for. Default: 15552000 (180 days).
|
|
73
|
+
# MCP_OAUTH_REFRESH_TOKEN_EXPIRY_SECONDS=15552000
|
|
74
|
+
|
|
75
|
+
# Optional. Directory where OAuth client registrations and tokens are
|
|
76
|
+
# persisted (oauth_tokens.json) so they survive server restarts.
|
|
77
|
+
# Default: .oauth-state (relative to the working directory).
|
|
78
|
+
# MCP_OAUTH_STATE_DIR=.oauth-state
|
|
79
|
+
|
|
80
|
+
# Networking (optional, defaults shown). The server only needs to bind to
|
|
81
|
+
# a local port - tailscale funnel handles TLS termination in front of it.
|
|
82
|
+
MCP_HOST=127.0.0.1
|
|
83
|
+
MCP_PORT=8000
|
|
84
|
+
|
|
85
|
+
# Optional. Default timezone for naive datetime inputs, day windows (agenda/filter bounds),
|
|
86
|
+
# and output timestamps returned to callers. Default: Europe/Berlin.
|
|
87
|
+
# Setting MCP_DEFAULT_TIMEZONE=UTC restores the previous UTC behavior.
|
|
88
|
+
# MCP_DEFAULT_TIMEZONE=Europe/Berlin
|
|
89
|
+
|
|
90
|
+
# Set to 1 to enable integration tests that hit the real Nextcloud instance
|
|
91
|
+
# configured above (see README for details). Leave unset for unit tests only.
|
|
92
|
+
# RUN_INTEGRATION_TESTS=1
|
|
93
|
+
|
|
94
|
+
# Name of an existing (ideally disposable) task list to use for integration
|
|
95
|
+
# tests. Tasks are created and deleted in this list during the test run.
|
|
96
|
+
# INTEGRATION_TEST_LIST=Test
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "uv"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
groups:
|
|
8
|
+
python-dependencies:
|
|
9
|
+
patterns: ["*"]
|
|
10
|
+
update-types: ["minor", "patch"]
|
|
11
|
+
|
|
12
|
+
- package-ecosystem: "github-actions"
|
|
13
|
+
directory: "/"
|
|
14
|
+
schedule:
|
|
15
|
+
interval: "weekly"
|
|
16
|
+
groups:
|
|
17
|
+
github-actions:
|
|
18
|
+
patterns: ["*"]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
lint-and-test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
python-version: ["3.10", "3.12"]
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Install uv
|
|
17
|
+
uses: astral-sh/setup-uv@v6
|
|
18
|
+
with:
|
|
19
|
+
python-version: ${{ matrix.python-version }}
|
|
20
|
+
enable-cache: true
|
|
21
|
+
cache-dependency-glob: "uv.lock"
|
|
22
|
+
|
|
23
|
+
- name: Install dependencies
|
|
24
|
+
run: uv sync --locked
|
|
25
|
+
|
|
26
|
+
- name: Lint with ruff
|
|
27
|
+
run: |
|
|
28
|
+
uv run ruff check .
|
|
29
|
+
uv run ruff format --check .
|
|
30
|
+
|
|
31
|
+
- name: Type check with mypy
|
|
32
|
+
run: uv run mypy src tests
|
|
33
|
+
|
|
34
|
+
- name: Run unit tests
|
|
35
|
+
run: |
|
|
36
|
+
uv run pytest -q --cov=src/nextcloud_organizer_mcp --cov-report=term-missing \
|
|
37
|
+
--cov-fail-under=90
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Scheduled integration test run against a real (containerized) Nextcloud
|
|
2
|
+
# instance (E11). This complements ci.yml's unit tests, which mock the
|
|
3
|
+
# `caldav` library entirely and never touch a real CalDAV server.
|
|
4
|
+
#
|
|
5
|
+
# NOTE: this workflow could not be executed/verified end-to-end while writing
|
|
6
|
+
# it (no way to run GitHub Actions service containers in this environment).
|
|
7
|
+
# The env vars it sets are wired to exactly what tests/test_integration.py
|
|
8
|
+
# reads (NEXTCLOUD_CALDAV_URL / NEXTCLOUD_USERNAME / NEXTCLOUD_APP_PASSWORD /
|
|
9
|
+
# INTEGRATION_TEST_LIST / RUN_INTEGRATION_TESTS), and the Nextcloud
|
|
10
|
+
# auto-setup env vars below follow the documented `nextcloud` Docker image
|
|
11
|
+
# contract - but the full flow (image boot, auto-install, calendar creation,
|
|
12
|
+
# first real test run) has only been reviewed, not observed. If it fails on
|
|
13
|
+
# its first scheduled/dispatched run, start by checking the "Wait for
|
|
14
|
+
# Nextcloud to be ready" and "Provision the test task list" steps' output.
|
|
15
|
+
name: Integration tests
|
|
16
|
+
|
|
17
|
+
on:
|
|
18
|
+
schedule:
|
|
19
|
+
# Mondays at 04:00 UTC.
|
|
20
|
+
- cron: "0 4 * * 1"
|
|
21
|
+
workflow_dispatch: {}
|
|
22
|
+
|
|
23
|
+
# Deliberately no `push`/`pull_request` trigger: this hits a real (if
|
|
24
|
+
# ephemeral, containerized) Nextcloud instance and is too slow/flaky to gate
|
|
25
|
+
# every PR on.
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
integration:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
# Fail the workflow (and surface it) on any test failure - no silent
|
|
31
|
+
# green runs.
|
|
32
|
+
continue-on-error: false
|
|
33
|
+
|
|
34
|
+
services:
|
|
35
|
+
nextcloud:
|
|
36
|
+
image: nextcloud:latest
|
|
37
|
+
ports:
|
|
38
|
+
- 8080:80
|
|
39
|
+
env:
|
|
40
|
+
# Auto-setup env vars documented by the official `nextcloud` image's
|
|
41
|
+
# entrypoint: presence of NEXTCLOUD_ADMIN_USER/PASSWORD plus a
|
|
42
|
+
# database config (SQLITE_DATABASE here, to avoid needing a
|
|
43
|
+
# separate DB service container for a throwaway test instance)
|
|
44
|
+
# triggers `occ maintenance:install` automatically on first boot.
|
|
45
|
+
SQLITE_DATABASE: nextcloud
|
|
46
|
+
NEXTCLOUD_ADMIN_USER: admin
|
|
47
|
+
NEXTCLOUD_ADMIN_PASSWORD: ${{ secrets.INTEGRATION_NEXTCLOUD_ADMIN_PASSWORD || 'nextcloud-ci-admin-pw' }}
|
|
48
|
+
|
|
49
|
+
env:
|
|
50
|
+
NEXTCLOUD_USERNAME: admin
|
|
51
|
+
# Real deployments use a per-app password generated under Settings ->
|
|
52
|
+
# Security; for this disposable, network-isolated CI instance the admin
|
|
53
|
+
# account password is used directly to keep provisioning simple - it
|
|
54
|
+
# only exists for the lifetime of the job's service container.
|
|
55
|
+
NEXTCLOUD_APP_PASSWORD: ${{ secrets.INTEGRATION_NEXTCLOUD_ADMIN_PASSWORD || 'nextcloud-ci-admin-pw' }}
|
|
56
|
+
NEXTCLOUD_CALDAV_URL: "http://localhost:8080/remote.php/dav/"
|
|
57
|
+
INTEGRATION_TEST_LIST: "Test"
|
|
58
|
+
RUN_INTEGRATION_TESTS: "1"
|
|
59
|
+
# The container is plain http:// (no TLS) - Settings.from_env() would
|
|
60
|
+
# normally refuse that (D8), but tests/test_integration.py builds
|
|
61
|
+
# CalDavService directly and never goes through Settings, so this
|
|
62
|
+
# isn't actually read today. Set anyway in case that changes.
|
|
63
|
+
NEXTCLOUD_ALLOW_INSECURE_HTTP: "1"
|
|
64
|
+
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/checkout@v4
|
|
67
|
+
|
|
68
|
+
- name: Install uv
|
|
69
|
+
uses: astral-sh/setup-uv@v6
|
|
70
|
+
with:
|
|
71
|
+
python-version: "3.12"
|
|
72
|
+
enable-cache: true
|
|
73
|
+
cache-dependency-glob: "uv.lock"
|
|
74
|
+
|
|
75
|
+
- name: Install dependencies
|
|
76
|
+
run: uv sync --locked
|
|
77
|
+
|
|
78
|
+
- name: Wait for Nextcloud to be ready
|
|
79
|
+
run: |
|
|
80
|
+
for i in $(seq 1 60); do
|
|
81
|
+
if curl -sf http://localhost:8080/status.php | grep -q '"installed":true'; then
|
|
82
|
+
echo "Nextcloud is up and installed."
|
|
83
|
+
exit 0
|
|
84
|
+
fi
|
|
85
|
+
echo "Waiting for Nextcloud... ($i/60)"
|
|
86
|
+
sleep 5
|
|
87
|
+
done
|
|
88
|
+
echo "Nextcloud did not become ready in time." >&2
|
|
89
|
+
exit 1
|
|
90
|
+
|
|
91
|
+
- name: Provision the test task list
|
|
92
|
+
run: |
|
|
93
|
+
container_id="$(docker ps -q --filter ancestor=nextcloud:latest)"
|
|
94
|
+
# The calendar app (bundled with Nextcloud, provides the CalDAV
|
|
95
|
+
# VTODO backend Tasks/this server both use) may ship disabled by
|
|
96
|
+
# default - make sure it's on before creating a calendar in it.
|
|
97
|
+
docker exec "$container_id" php occ app:enable calendar
|
|
98
|
+
# `dav:create-calendar` (part of the bundled DAV app) creates a
|
|
99
|
+
# calendar (= task list, from this server's point of view) for a
|
|
100
|
+
# user by uid.
|
|
101
|
+
docker exec "$container_id" php occ dav:create-calendar "$NEXTCLOUD_USERNAME" "$INTEGRATION_TEST_LIST"
|
|
102
|
+
|
|
103
|
+
- name: Run integration tests
|
|
104
|
+
run: uv run pytest tests/test_integration.py -q
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
|
|
13
|
+
- name: Install uv
|
|
14
|
+
uses: astral-sh/setup-uv@v6
|
|
15
|
+
|
|
16
|
+
- name: Check tag matches project version
|
|
17
|
+
run: |
|
|
18
|
+
version="$(uv version --short)"
|
|
19
|
+
if [ "v${version}" != "${GITHUB_REF_NAME}" ]; then
|
|
20
|
+
echo "Tag ${GITHUB_REF_NAME} does not match project version ${version}" >&2
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
- name: Build sdist and wheel
|
|
25
|
+
run: uv build
|
|
26
|
+
|
|
27
|
+
- uses: actions/upload-artifact@v4
|
|
28
|
+
with:
|
|
29
|
+
name: dist
|
|
30
|
+
path: dist/
|
|
31
|
+
|
|
32
|
+
publish:
|
|
33
|
+
needs: build
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
environment:
|
|
36
|
+
name: pypi
|
|
37
|
+
url: https://pypi.org/p/nextcloud-organizer-mcp
|
|
38
|
+
permissions:
|
|
39
|
+
# Required for PyPI trusted publishing (OIDC); no API token is stored.
|
|
40
|
+
id-token: write
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/download-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
name: dist
|
|
45
|
+
path: dist/
|
|
46
|
+
|
|
47
|
+
- name: Publish to PyPI
|
|
48
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
.eggs/
|
|
5
|
+
|
|
6
|
+
.venv/
|
|
7
|
+
venv/
|
|
8
|
+
env/
|
|
9
|
+
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
.mypy_cache/
|
|
13
|
+
.coverage
|
|
14
|
+
htmlcov/
|
|
15
|
+
dist/
|
|
16
|
+
build/
|
|
17
|
+
|
|
18
|
+
.env
|
|
19
|
+
.env.local
|
|
20
|
+
|
|
21
|
+
# Persisted OAuth clients/tokens (PersonalAuthProvider), contains secrets.
|
|
22
|
+
.oauth-state/
|
|
23
|
+
|
|
24
|
+
.DS_Store
|
|
25
|
+
|
|
26
|
+
# graphify skill output (generated knowledge-graph artifacts, not project source).
|
|
27
|
+
graphify-out/
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Local hooks that shell out to `uv run`, so the tool versions used here are
|
|
2
|
+
# always the ones pinned in uv.lock - no separate, potentially-drifting
|
|
3
|
+
# pre-commit-managed toolchain to keep in sync (E10). Run `pre-commit install`
|
|
4
|
+
# once (see CONTRIBUTING.md) to wire these into `git commit`.
|
|
5
|
+
repos:
|
|
6
|
+
- repo: local
|
|
7
|
+
hooks:
|
|
8
|
+
- id: ruff-check
|
|
9
|
+
name: ruff check --fix
|
|
10
|
+
entry: uv run ruff check --fix
|
|
11
|
+
language: system
|
|
12
|
+
types: [python]
|
|
13
|
+
|
|
14
|
+
- id: ruff-format
|
|
15
|
+
name: ruff format
|
|
16
|
+
entry: uv run ruff format
|
|
17
|
+
language: system
|
|
18
|
+
types: [python]
|
|
19
|
+
|
|
20
|
+
- id: mypy
|
|
21
|
+
name: mypy src tests
|
|
22
|
+
entry: uv run mypy src tests
|
|
23
|
+
language: system
|
|
24
|
+
pass_filenames: false
|
|
25
|
+
types: [python]
|