immich-api 0.2.2__tar.gz → 0.2.3__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.
- {immich_api-0.2.2 → immich_api-0.2.3}/.bumpversion.cfg +1 -1
- {immich_api-0.2.2 → immich_api-0.2.3}/.pre-commit-config.yaml +0 -12
- {immich_api-0.2.2/immich_api.egg-info → immich_api-0.2.3}/PKG-INFO +4 -4
- {immich_api-0.2.2 → immich_api-0.2.3}/docker/Dockerfile +1 -1
- immich_api-0.2.3/immich_api/connector_sources.py +145 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/ontology/immich.ttl +1 -1
- {immich_api-0.2.2 → immich_api-0.2.3/immich_api.egg-info}/PKG-INFO +4 -4
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api.egg-info/SOURCES.txt +1 -8
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api.egg-info/entry_points.txt +0 -3
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api.egg-info/requires.txt +3 -3
- {immich_api-0.2.2 → immich_api-0.2.3}/pyproject.toml +5 -8
- {immich_api-0.2.2 → immich_api-0.2.3}/requirements.txt +1 -1
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/generate_immich_content.py +1 -54
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/parity_support.py +3 -3
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_fleet_name.py +2 -10
- immich_api-0.2.3/tests/test_immich_content.py +44 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_kg_ingest.py +0 -30
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_operation_parity.py +75 -11
- immich_api-0.2.2/immich_api/connector_manifest.yml +0 -212
- immich_api-0.2.2/immich_api/connectors/mcp_source_presets.json +0 -3
- immich_api-0.2.2/immich_api/connectors/tool_schema_fingerprints.json +0 -1
- immich_api-0.2.2/scripts/generate_tool_schemas.py +0 -100
- immich_api-0.2.2/scripts/generated_schema_clones.py +0 -163
- immich_api-0.2.2/scripts/verify_generated_schemas.py +0 -111
- immich_api-0.2.2/tests/test_generated_schema_policy.py +0 -159
- immich_api-0.2.2/tests/test_immich_content.py +0 -149
- immich_api-0.2.2/tests/test_source_image.py +0 -24
- {immich_api-0.2.2 → immich_api-0.2.3}/.config/spec-dashboard.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.github/workflows/connector-pr.yml +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.github/workflows/pages.yml +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.github/workflows/pipeline.yml +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.github/workflows/scanners.yml +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.github/workflows/windows-ci.yml +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/provenance.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/scripts/sync_mkdocs_theme.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/README.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/assets/brands/agent-connector-sdk-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/assets/brands/agent-terminal-ui-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/assets/brands/agent-utilities-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/assets/brands/agent-webui-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/assets/brands/epistemic-graph-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/assets/brands/geniusbot-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/assets/brands/graph-os-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/assets/favicon.svg +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/assets/graph-mark.svg +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/assets/runtime-architecture.mmd +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/assets/runtime-architecture.svg +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/base.mkdocs.yml +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/extra.css +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/glossary.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/.pipeline-theme/templates/mkdocs-theme/overrides/main.html +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/LICENSE +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/MANIFEST.in +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/README.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docker/debug.Dockerfile +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docker/mcp.compose.yml +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docker/starship.toml +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/agent-readiness.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/agent-readiness.schema.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/architecture.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/assets/brands/agent-connector-sdk-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/assets/brands/agent-terminal-ui-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/assets/brands/agent-utilities-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/assets/brands/agent-webui-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/assets/brands/epistemic-graph-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/assets/brands/geniusbot-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/assets/brands/graph-os-logo-v1.png +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/assets/favicon.svg +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/assets/graph-mark.svg +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/assets/runtime-architecture.mmd +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/assets/runtime-architecture.svg +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/capabilities/api.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/capabilities/mcp.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/concepts.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/deployment.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/glossary.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/immich-capabilities.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/index.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/installation.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/openapi-parity.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/overview.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/platform.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/spec-delivery.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/stylesheets/extra.css +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/docs/usage.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/__init__.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/__main__.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/album_metadata.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/api/__init__.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/api/api_client_system.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/auth.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/connectors/__init__.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/error_authority.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/error_rendering.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/immich_input_models.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/immich_response_models.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/kg_ingest.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/mcp/__init__.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/mcp/album_sample.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/mcp_config.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/mcp_server.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/ontology/__init__.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/ontology/schema-provenance.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/ontology/shapes/immich.ttl +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/openapi_auth_scheme.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/openapi_contract.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/openapi_execution.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/openapi_inventory.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/openapi_request.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/openapi_response.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/openapi_runtime.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/__init__.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/check_openapi_parity.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/openapi_discovery.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/openapi_parity.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/openapi_provider_evidence.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/openapi_provider_overlay.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/openapi_provider_responses.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/openapi_schema.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/openapi_schema_budget.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/openapi_schema_inputs.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/openapi_schema_types.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/openapi_security.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/openapi_source_parity.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/openapi_transport_parity.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/unicode_patterns.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/parity/unicode_properties.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/prompts/__init__.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/prompts/immich_album_review.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/prompts/immich_asset_metadata.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/prompts/immich_person_record.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/prompts/immich_specialist.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/prompts/main_agent.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/skills/__init__.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/skills/immich-album-review/SKILL.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/skills/immich-asset-metadata/SKILL.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/skills/immich-health/SKILL.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api/skills/immich-person-record/SKILL.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api.egg-info/dependency_links.txt +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/immich_api.egg-info/top_level.txt +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/mkdocs.yml +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/pytest.ini +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/agent_readiness_tck.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/bootstrap.sh +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/bootstrap_environment.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/bootstrap_sources.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/check_connector_contract.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/check_import_safety.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/check_workspace_source_drift.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/generate_agent_readiness.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/measure_operation_parity.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/reviewed_secret_history.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/security_sanitizer.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/select_python.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/upstream_evidence.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/verify_api_integration.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/scripts/workspace_sources.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/setup.cfg +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/README.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/connector-content/plan.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/connector-content/requirements.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/connector-content/spec.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/connector-content/status.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/connector-content/tasks.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/connector-content/test-spec.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/immich-api/plan.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/immich-api/requirements.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/immich-api/spec.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/immich-api/status.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/immich-api/tasks.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/specs/immich-api/test-spec.md +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/__init__.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/conftest.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/fixtures/native-client-budget.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/fixtures/operation-cases.json +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/operation_fixtures.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_album_metadata.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_api_wrapper.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_auth.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_concept_parity.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_default_content_surfaces.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_error_authority.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_immich_mcp_validation.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_init_dynamics.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_oauth_redirect_response.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_openapi_auth_provider.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_reviewed_secret_history.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_session_auth_isolation.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_startup.py +0 -0
- {immich_api-0.2.2 → immich_api-0.2.3}/tests/test_upstream_evidence.py +0 -0
|
@@ -20,12 +20,6 @@ repos:
|
|
|
20
20
|
stages: [pre-push]
|
|
21
21
|
- id: kiss-census
|
|
22
22
|
stages: [pre-push]
|
|
23
|
-
- id: jscpd-differential
|
|
24
|
-
entry: python scripts/generated_schema_clones.py differential
|
|
25
|
-
stages: [pre-push]
|
|
26
|
-
- id: jscpd-census
|
|
27
|
-
entry: python scripts/generated_schema_clones.py census
|
|
28
|
-
stages: [pre-push]
|
|
29
23
|
- id: public-surface
|
|
30
24
|
- id: security-sanitizer
|
|
31
25
|
- id: secret-history
|
|
@@ -72,12 +66,6 @@ repos:
|
|
|
72
66
|
language: system
|
|
73
67
|
pass_filenames: false
|
|
74
68
|
always_run: true
|
|
75
|
-
- id: connector-tool-schemas
|
|
76
|
-
name: Live SDK input and output schema contracts
|
|
77
|
-
entry: python scripts/generate_tool_schemas.py --check
|
|
78
|
-
language: system
|
|
79
|
-
pass_filenames: false
|
|
80
|
-
always_run: true
|
|
81
69
|
- id: pytest
|
|
82
70
|
name: Generated connector contracts
|
|
83
71
|
entry: python -m pytest tests -q
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: immich-api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Immich Api API + MCP Server
|
|
5
5
|
Author: Repository Maintainers
|
|
6
6
|
License: MIT
|
|
@@ -16,11 +16,11 @@ Requires-Dist: rfc3986-validator<0.2,>=0.1.1
|
|
|
16
16
|
Requires-Dist: rfc3339-validator<0.2,>=0.1.4
|
|
17
17
|
Requires-Dist: jsonschema<5,>=4.23
|
|
18
18
|
Requires-Dist: regex>=2026.9.29
|
|
19
|
-
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.
|
|
19
|
+
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1
|
|
20
20
|
Provides-Extra: mcp
|
|
21
|
-
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.
|
|
21
|
+
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1; extra == "mcp"
|
|
22
22
|
Provides-Extra: all
|
|
23
|
-
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.
|
|
23
|
+
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1; extra == "all"
|
|
24
24
|
Provides-Extra: test
|
|
25
25
|
Requires-Dist: pytest-xdist>=3.6.0; extra == "test"
|
|
26
26
|
Requires-Dist: pytest; extra == "test"
|
|
@@ -20,7 +20,7 @@ ENV HOST=${HOST} \
|
|
|
20
20
|
XDG_CONFIG_HOME=/tmp/.config \
|
|
21
21
|
XDG_CACHE_HOME=/tmp/.cache
|
|
22
22
|
# Fixed identity for least-privilege runtime and stable volume ownership.
|
|
23
|
-
RUN pip install --only-binary :all: immich-api[mcp]==0.2.
|
|
23
|
+
RUN pip install --only-binary :all: immich-api[mcp]==0.2.3 \
|
|
24
24
|
&& groupadd --system --gid 10001 app \
|
|
25
25
|
&& useradd --system --uid 10001 --gid 10001 --no-create-home \
|
|
26
26
|
--home-dir /tmp --shell /usr/sbin/nologin app
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""Data sources of this connector, declared by tool name (generated by connector-ontology-map migrate).
|
|
2
|
+
|
|
3
|
+
Served live as ``connector://resources``. Regenerate by editing the declarations, not the tools.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# ruff: noqa: E501
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from agent_connector_sdk.ingest.sources import IngestSourceDeclaration, IngestSourceSpec
|
|
12
|
+
|
|
13
|
+
CONNECTOR: str = "immich"
|
|
14
|
+
|
|
15
|
+
SOURCES: tuple[Any, ...] = ()
|
|
16
|
+
|
|
17
|
+
SCHEMA_MAPPINGS: dict[str, Any] = {
|
|
18
|
+
"ImmichAlbum": {
|
|
19
|
+
"fields": {
|
|
20
|
+
"immichAlbumAlbumName": "xsd:string",
|
|
21
|
+
"immichAlbumAlbumThumbnailAssetId": "xsd:string",
|
|
22
|
+
"immichAlbumAssetCount": "xsd:integer",
|
|
23
|
+
"immichAlbumCreatedAt": "xsd:dateTime",
|
|
24
|
+
"immichAlbumHasSharedLink": "xsd:boolean",
|
|
25
|
+
"immichAlbumId": "xsd:string",
|
|
26
|
+
"immichAlbumShared": "xsd:boolean",
|
|
27
|
+
"immichAlbumUpdatedAt": "xsd:dateTime",
|
|
28
|
+
},
|
|
29
|
+
"ontology_class": "ImmichAlbum",
|
|
30
|
+
},
|
|
31
|
+
"ImmichAlbumMembership": {
|
|
32
|
+
"fields": {
|
|
33
|
+
"immichAlbumMembershipRole": "xsd:string",
|
|
34
|
+
},
|
|
35
|
+
"ontology_class": "ImmichAlbumMembership",
|
|
36
|
+
},
|
|
37
|
+
"ImmichAsset": {
|
|
38
|
+
"fields": {
|
|
39
|
+
"immichAssetDuration": "xsd:integer",
|
|
40
|
+
"immichAssetFileCreatedAt": "xsd:dateTime",
|
|
41
|
+
"immichAssetHeight": "xsd:integer",
|
|
42
|
+
"immichAssetId": "xsd:string",
|
|
43
|
+
"immichAssetIsArchived": "xsd:boolean",
|
|
44
|
+
"immichAssetIsFavorite": "xsd:boolean",
|
|
45
|
+
"immichAssetIsTrashed": "xsd:boolean",
|
|
46
|
+
"immichAssetOriginalMimeType": "xsd:string",
|
|
47
|
+
"immichAssetType": "xsd:string",
|
|
48
|
+
"immichAssetUpdatedAt": "xsd:dateTime",
|
|
49
|
+
"immichAssetVisibility": "xsd:string",
|
|
50
|
+
"immichAssetWidth": "xsd:integer",
|
|
51
|
+
},
|
|
52
|
+
"ontology_class": "ImmichAsset",
|
|
53
|
+
},
|
|
54
|
+
"ImmichAssetStack": {
|
|
55
|
+
"fields": {
|
|
56
|
+
"immichAssetStackAssetCount": "xsd:integer",
|
|
57
|
+
"immichAssetStackId": "xsd:string",
|
|
58
|
+
"immichAssetStackPrimaryAssetId": "xsd:string",
|
|
59
|
+
},
|
|
60
|
+
"ontology_class": "ImmichAssetStack",
|
|
61
|
+
},
|
|
62
|
+
"ImmichLibrary": {
|
|
63
|
+
"fields": {
|
|
64
|
+
"immichLibraryAssetCount": "xsd:integer",
|
|
65
|
+
"immichLibraryCreatedAt": "xsd:dateTime",
|
|
66
|
+
"immichLibraryId": "xsd:string",
|
|
67
|
+
"immichLibraryName": "xsd:string",
|
|
68
|
+
"immichLibraryUpdatedAt": "xsd:dateTime",
|
|
69
|
+
},
|
|
70
|
+
"ontology_class": "ImmichLibrary",
|
|
71
|
+
},
|
|
72
|
+
"ImmichPersonRecord": {
|
|
73
|
+
"fields": {
|
|
74
|
+
"immichPersonRecordId": "xsd:string",
|
|
75
|
+
"immichPersonRecordIsFavorite": "xsd:boolean",
|
|
76
|
+
"immichPersonRecordIsHidden": "xsd:boolean",
|
|
77
|
+
"immichPersonRecordName": "xsd:string",
|
|
78
|
+
"immichPersonRecordUpdatedAt": "xsd:dateTime",
|
|
79
|
+
},
|
|
80
|
+
"ontology_class": "ImmichPersonRecord",
|
|
81
|
+
},
|
|
82
|
+
"ImmichTag": {
|
|
83
|
+
"fields": {
|
|
84
|
+
"immichTagCreatedAt": "xsd:dateTime",
|
|
85
|
+
"immichTagId": "xsd:string",
|
|
86
|
+
"immichTagName": "xsd:string",
|
|
87
|
+
"immichTagUpdatedAt": "xsd:dateTime",
|
|
88
|
+
},
|
|
89
|
+
"ontology_class": "ImmichTag",
|
|
90
|
+
},
|
|
91
|
+
"ImmichUser": {
|
|
92
|
+
"fields": {
|
|
93
|
+
"immichUserId": "xsd:string",
|
|
94
|
+
"immichUserName": "xsd:string",
|
|
95
|
+
},
|
|
96
|
+
"ontology_class": "ImmichUser",
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
RESOURCES: tuple[dict[str, str], ...] = (
|
|
101
|
+
{
|
|
102
|
+
"name": "ImmichAsset",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "ImmichAlbum",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"name": "ImmichPersonRecord",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"name": "ImmichUser",
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"name": "ImmichLibrary",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"name": "ImmichAlbumMembership",
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"name": "ImmichTag",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"name": "ImmichAssetStack",
|
|
124
|
+
},
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def declaration() -> IngestSourceDeclaration:
|
|
129
|
+
"""The declaration the server assembles from this module."""
|
|
130
|
+
specs: list[IngestSourceSpec] = []
|
|
131
|
+
for item in SOURCES:
|
|
132
|
+
for entry in item["connector_sources"]:
|
|
133
|
+
body: dict[str, Any] = {
|
|
134
|
+
k: v for k, v in entry.items() if k not in ("tool", "mapping")
|
|
135
|
+
}
|
|
136
|
+
spec = {**body, "tools": (entry["tool"],)}
|
|
137
|
+
specs.append(IngestSourceSpec.model_validate(spec))
|
|
138
|
+
return IngestSourceDeclaration.model_validate(
|
|
139
|
+
{
|
|
140
|
+
"connector": CONNECTOR,
|
|
141
|
+
"sources": specs,
|
|
142
|
+
"schema_mappings": SCHEMA_MAPPINGS,
|
|
143
|
+
"resources": RESOURCES,
|
|
144
|
+
}
|
|
145
|
+
)
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
<urn:sha256:7db8383741eeb5c5c8c87a6221cd1cdd1206c8b1190b83363c64223a00bb020b> a prov:Entity ; rdfs:label "Immich 3.2.2 OpenAPI source bytes" .
|
|
10
10
|
|
|
11
|
-
<http://knuckles.team/kg/immich> a owl:Ontology ;
|
|
11
|
+
<http://knuckles.team/kg/immich> a owl:Ontology ; prov:wasDerivedFrom <urn:sha256:7db8383741eeb5c5c8c87a6221cd1cdd1206c8b1190b83363c64223a00bb020b> ; rdfs:comment "Selected structural DTO model. No live ingestion or identity equivalence is asserted." .
|
|
12
12
|
|
|
13
13
|
:ImmichAsset a owl:Class ; rdfs:comment "Structural projection of AssetResponseDto." ; prov:wasDerivedFrom <urn:sha256:7db8383741eeb5c5c8c87a6221cd1cdd1206c8b1190b83363c64223a00bb020b#/components/schemas/AssetResponseDto> .
|
|
14
14
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: immich-api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Immich Api API + MCP Server
|
|
5
5
|
Author: Repository Maintainers
|
|
6
6
|
License: MIT
|
|
@@ -16,11 +16,11 @@ Requires-Dist: rfc3986-validator<0.2,>=0.1.1
|
|
|
16
16
|
Requires-Dist: rfc3339-validator<0.2,>=0.1.4
|
|
17
17
|
Requires-Dist: jsonschema<5,>=4.23
|
|
18
18
|
Requires-Dist: regex>=2026.9.29
|
|
19
|
-
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.
|
|
19
|
+
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1
|
|
20
20
|
Provides-Extra: mcp
|
|
21
|
-
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.
|
|
21
|
+
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1; extra == "mcp"
|
|
22
22
|
Provides-Extra: all
|
|
23
|
-
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.
|
|
23
|
+
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.4.1; extra == "all"
|
|
24
24
|
Provides-Extra: test
|
|
25
25
|
Requires-Dist: pytest-xdist>=3.6.0; extra == "test"
|
|
26
26
|
Requires-Dist: pytest; extra == "test"
|
|
@@ -67,7 +67,7 @@ immich_api/__init__.py
|
|
|
67
67
|
immich_api/__main__.py
|
|
68
68
|
immich_api/album_metadata.py
|
|
69
69
|
immich_api/auth.py
|
|
70
|
-
immich_api/
|
|
70
|
+
immich_api/connector_sources.py
|
|
71
71
|
immich_api/error_authority.py
|
|
72
72
|
immich_api/error_rendering.py
|
|
73
73
|
immich_api/immich_input_models.py
|
|
@@ -91,8 +91,6 @@ immich_api.egg-info/top_level.txt
|
|
|
91
91
|
immich_api/api/__init__.py
|
|
92
92
|
immich_api/api/api_client_system.py
|
|
93
93
|
immich_api/connectors/__init__.py
|
|
94
|
-
immich_api/connectors/mcp_source_presets.json
|
|
95
|
-
immich_api/connectors/tool_schema_fingerprints.json
|
|
96
94
|
immich_api/mcp/__init__.py
|
|
97
95
|
immich_api/mcp/album_sample.py
|
|
98
96
|
immich_api/ontology/__init__.py
|
|
@@ -135,15 +133,12 @@ scripts/check_import_safety.py
|
|
|
135
133
|
scripts/check_workspace_source_drift.py
|
|
136
134
|
scripts/generate_agent_readiness.py
|
|
137
135
|
scripts/generate_immich_content.py
|
|
138
|
-
scripts/generate_tool_schemas.py
|
|
139
|
-
scripts/generated_schema_clones.py
|
|
140
136
|
scripts/measure_operation_parity.py
|
|
141
137
|
scripts/reviewed_secret_history.py
|
|
142
138
|
scripts/security_sanitizer.py
|
|
143
139
|
scripts/select_python.py
|
|
144
140
|
scripts/upstream_evidence.py
|
|
145
141
|
scripts/verify_api_integration.py
|
|
146
|
-
scripts/verify_generated_schemas.py
|
|
147
142
|
scripts/workspace_sources.py
|
|
148
143
|
specs/README.md
|
|
149
144
|
specs/connector-content/plan.md
|
|
@@ -169,7 +164,6 @@ tests/test_concept_parity.py
|
|
|
169
164
|
tests/test_default_content_surfaces.py
|
|
170
165
|
tests/test_error_authority.py
|
|
171
166
|
tests/test_fleet_name.py
|
|
172
|
-
tests/test_generated_schema_policy.py
|
|
173
167
|
tests/test_immich_content.py
|
|
174
168
|
tests/test_immich_mcp_validation.py
|
|
175
169
|
tests/test_init_dynamics.py
|
|
@@ -179,7 +173,6 @@ tests/test_openapi_auth_provider.py
|
|
|
179
173
|
tests/test_operation_parity.py
|
|
180
174
|
tests/test_reviewed_secret_history.py
|
|
181
175
|
tests/test_session_auth_isolation.py
|
|
182
|
-
tests/test_source_image.py
|
|
183
176
|
tests/test_startup.py
|
|
184
177
|
tests/test_upstream_evidence.py
|
|
185
178
|
tests/fixtures/native-client-budget.json
|
|
@@ -10,8 +10,5 @@ immich-api = immich_api.prompts
|
|
|
10
10
|
[agent_utilities.skill_providers]
|
|
11
11
|
immich-api = immich_api.skills
|
|
12
12
|
|
|
13
|
-
[agent_utilities.source_connector_providers]
|
|
14
|
-
immich-api = immich_api.connectors
|
|
15
|
-
|
|
16
13
|
[console_scripts]
|
|
17
14
|
immich-mcp = immich_api.mcp_server:mcp_server
|
|
@@ -2,13 +2,13 @@ rfc3986-validator<0.2,>=0.1.1
|
|
|
2
2
|
rfc3339-validator<0.2,>=0.1.4
|
|
3
3
|
jsonschema<5,>=4.23
|
|
4
4
|
regex>=2026.9.29
|
|
5
|
-
agent-connector-sdk[mcp]<1.0.0,>=0.
|
|
5
|
+
agent-connector-sdk[mcp]<1.0.0,>=0.4.1
|
|
6
6
|
|
|
7
7
|
[all]
|
|
8
|
-
agent-connector-sdk[mcp]<1.0.0,>=0.
|
|
8
|
+
agent-connector-sdk[mcp]<1.0.0,>=0.4.1
|
|
9
9
|
|
|
10
10
|
[mcp]
|
|
11
|
-
agent-connector-sdk[mcp]<1.0.0,>=0.
|
|
11
|
+
agent-connector-sdk[mcp]<1.0.0,>=0.4.1
|
|
12
12
|
|
|
13
13
|
[test]
|
|
14
14
|
pytest-xdist>=3.6.0
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "immich-api"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.3"
|
|
8
8
|
description = "Immich Api API + MCP Server"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
classifiers = [ "Development Status :: 4 - Beta", "License :: OSI Approved :: MIT License", "Environment :: Console", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3",]
|
|
@@ -14,7 +14,7 @@ dependencies = [
|
|
|
14
14
|
"rfc3339-validator>=0.1.4,<0.2",
|
|
15
15
|
"jsonschema>=4.23,<5",
|
|
16
16
|
"regex>=2026.9.29",
|
|
17
|
-
"agent-connector-sdk[mcp]>=0.
|
|
17
|
+
"agent-connector-sdk[mcp]>=0.4.1,<1.0.0",
|
|
18
18
|
]
|
|
19
19
|
[[project.authors]]
|
|
20
20
|
name = "Repository Maintainers"
|
|
@@ -23,9 +23,9 @@ name = "Repository Maintainers"
|
|
|
23
23
|
text = "MIT"
|
|
24
24
|
|
|
25
25
|
[project.optional-dependencies]
|
|
26
|
-
mcp = [ "agent-connector-sdk[mcp]>=0.
|
|
26
|
+
mcp = [ "agent-connector-sdk[mcp]>=0.4.1,<1.0.0",]
|
|
27
27
|
all = [
|
|
28
|
-
"agent-connector-sdk[mcp]>=0.
|
|
28
|
+
"agent-connector-sdk[mcp]>=0.4.1,<1.0.0",
|
|
29
29
|
]
|
|
30
30
|
test = [
|
|
31
31
|
"pytest-xdist>=3.6.0", "pytest", "pytest-asyncio", "pytest-cov",]
|
|
@@ -46,9 +46,6 @@ immich-api = "immich_api.prompts"
|
|
|
46
46
|
[project.entry-points."agent_utilities.ontology_providers"]
|
|
47
47
|
immich-api = "immich_api.ontology"
|
|
48
48
|
|
|
49
|
-
[project.entry-points."agent_utilities.source_connector_providers"]
|
|
50
|
-
immich-api = "immich_api.connectors"
|
|
51
|
-
|
|
52
49
|
# The one declared connector identity: the fleet name (SDK-CONNECTOR-CONTROL-R071).
|
|
53
50
|
[project.entry-points."agent_connector_sdk.connector"]
|
|
54
51
|
immich = "immich_api"
|
|
@@ -87,7 +84,7 @@ dev = [
|
|
|
87
84
|
]
|
|
88
85
|
|
|
89
86
|
[tool.setuptools.package-data]
|
|
90
|
-
immich_api = [ "openapi_inventory.json", "parity/unicode_properties.json", "openapi_contract.json", "mcp_config.json", "prompts/**", "skills/**", "ontology/**", "connectors/**",
|
|
87
|
+
immich_api = [ "openapi_inventory.json", "parity/unicode_properties.json", "openapi_contract.json", "mcp_config.json", "prompts/**", "skills/**", "ontology/**", "connectors/**", ]
|
|
91
88
|
|
|
92
89
|
[tool.ruff.lint]
|
|
93
90
|
select = [ "E", "F", "I", "UP", "B",]
|
|
@@ -81,7 +81,7 @@ def artifacts():
|
|
|
81
81
|
f'<{source}> a prov:Entity ; rdfs:label "Immich 3.2.2 OpenAPI source bytes" .\n',
|
|
82
82
|
]
|
|
83
83
|
ontology.append(
|
|
84
|
-
f'<http://knuckles.team/kg/immich> a owl:Ontology ;
|
|
84
|
+
f'<http://knuckles.team/kg/immich> a owl:Ontology ; prov:wasDerivedFrom <{source}> ; rdfs:comment "Selected structural DTO model. No live ingestion or identity equivalence is asserted." .\n'
|
|
85
85
|
)
|
|
86
86
|
shapes = [PREFIXES]
|
|
87
87
|
resources, mappings, provenance = [], {}, []
|
|
@@ -180,58 +180,6 @@ def artifacts():
|
|
|
180
180
|
resources.append({"name": class_name, "relations": relations})
|
|
181
181
|
mappings[class_name] = {"ontology_class": class_name, "fields": fields}
|
|
182
182
|
ontology_text, shapes_text = "\n".join(ontology), "\n".join(shapes)
|
|
183
|
-
manifest = json.loads((PACKAGE / "connector_manifest.yml").read_text())
|
|
184
|
-
manifest.update(
|
|
185
|
-
{
|
|
186
|
-
"resources": resources,
|
|
187
|
-
"identity": {
|
|
188
|
-
"id_field": {
|
|
189
|
-
name: "immich" + name.removeprefix("Immich") + "Id"
|
|
190
|
-
for name in mappings
|
|
191
|
-
if name != "ImmichAlbumMembership"
|
|
192
|
-
},
|
|
193
|
-
"title_field": {
|
|
194
|
-
"ImmichAlbum": "immichAlbumAlbumName",
|
|
195
|
-
"ImmichPersonRecord": "immichPersonRecordName",
|
|
196
|
-
"ImmichUser": "immichUserName",
|
|
197
|
-
"ImmichLibrary": "immichLibraryName",
|
|
198
|
-
"ImmichTag": "immichTagName",
|
|
199
|
-
},
|
|
200
|
-
"updated_field": {
|
|
201
|
-
"ImmichAlbum": "immichAlbumUpdatedAt",
|
|
202
|
-
"ImmichAsset": "immichAssetUpdatedAt",
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
"schema_mappings": mappings,
|
|
206
|
-
"policy": {
|
|
207
|
-
"pii_fields": {
|
|
208
|
-
"ImmichAlbum": ["immichAlbumAlbumName"],
|
|
209
|
-
"ImmichPersonRecord": ["immichPersonRecordName"],
|
|
210
|
-
"ImmichUser": ["immichUserName"],
|
|
211
|
-
"ImmichTag": ["immichTagName"],
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
"provenance": {
|
|
215
|
-
"generated_by": "scripts/generate_immich_content.py",
|
|
216
|
-
"source_artifacts": [
|
|
217
|
-
"openapi_contract.json",
|
|
218
|
-
"ontology/schema-provenance.json",
|
|
219
|
-
"ontology/immich.ttl",
|
|
220
|
-
"ontology/shapes/immich.ttl",
|
|
221
|
-
],
|
|
222
|
-
"integrity": {
|
|
223
|
-
"algorithm": "sha256",
|
|
224
|
-
"hash": hashlib.sha256(ontology_text.encode()).hexdigest(),
|
|
225
|
-
},
|
|
226
|
-
},
|
|
227
|
-
"review_todos": [
|
|
228
|
-
"Structural schema declarations are not evidence of live EG capture or semantic identity alignment.",
|
|
229
|
-
"Only the bounded album metadata projection is implemented for ingestion; remaining DTO classes are structural declarations.",
|
|
230
|
-
"Require explicit source/account binding, existing scoped credentials and a verified EG receipt/readback before enabling ingestion.",
|
|
231
|
-
"Ontology integrity is a byte SHA256, not canonical RDF or release certification.",
|
|
232
|
-
],
|
|
233
|
-
}
|
|
234
|
-
)
|
|
235
183
|
evidence = {
|
|
236
184
|
"status": "schema-derived; live ingestion unverified",
|
|
237
185
|
"source_version": "3.2.2",
|
|
@@ -263,7 +211,6 @@ def artifacts():
|
|
|
263
211
|
evidence, indent=2, sort_keys=True
|
|
264
212
|
)
|
|
265
213
|
+ "\n",
|
|
266
|
-
PACKAGE / "connector_manifest.yml": json.dumps(manifest, indent=2) + "\n",
|
|
267
214
|
}
|
|
268
215
|
|
|
269
216
|
|
|
@@ -61,7 +61,6 @@ async def native_initial_discovery(client):
|
|
|
61
61
|
|
|
62
62
|
async def native_discovery(client, name):
|
|
63
63
|
"""Verify one complete tool so discovery has its own bounded test budget."""
|
|
64
|
-
await asyncio.sleep(0.12)
|
|
65
64
|
result = await client.call_tool(
|
|
66
65
|
"search_tools", {"pattern": "^" + re.escape(name) + r"(?:\s|$)"}
|
|
67
66
|
)
|
|
@@ -113,11 +112,12 @@ class DiscoveredClient:
|
|
|
113
112
|
|
|
114
113
|
|
|
115
114
|
@asynccontextmanager
|
|
116
|
-
async def isolated_native_client(server, elicitation_handler):
|
|
115
|
+
async def isolated_native_client(server, elicitation_handler, pace=0.22):
|
|
117
116
|
"""Drain outstanding calls and close the protocol before the next provider."""
|
|
118
117
|
# Each fresh client adds server/discover and result-validation tools/list.
|
|
119
118
|
# Reserve those two requests at the unchanged SDK limit of 10 requests/s.
|
|
120
|
-
|
|
119
|
+
if pace:
|
|
120
|
+
await asyncio.sleep(pace)
|
|
121
121
|
async with Client(
|
|
122
122
|
server, elicitation_handler=elicitation_handler, timeout=10
|
|
123
123
|
) as native:
|
|
@@ -3,12 +3,11 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import ast
|
|
6
|
-
import json
|
|
7
|
-
import re
|
|
8
6
|
import tomllib
|
|
9
7
|
from pathlib import Path
|
|
10
8
|
|
|
11
9
|
import pytest
|
|
10
|
+
from agent_connector_sdk.connector_identity import connector_name
|
|
12
11
|
|
|
13
12
|
ROOT = Path(__file__).resolve().parents[1]
|
|
14
13
|
PACKAGE = ROOT / "immich_api"
|
|
@@ -38,13 +37,6 @@ def test_connector_name_is_the_fleet_name() -> None:
|
|
|
38
37
|
assert pyproject["project"]["entry-points"]["agent_connector_sdk.connector"] == {
|
|
39
38
|
FLEET: "immich_api"
|
|
40
39
|
}
|
|
41
|
-
|
|
42
|
-
match = re.search(r'^\s*"?connector"?\s*:\s*"?([^"\s,]+)', manifest, re.MULTILINE)
|
|
43
|
-
assert match is not None and match.group(1) == FLEET
|
|
44
|
-
fingerprints = PACKAGE / "connectors" / "tool_schema_fingerprints.json"
|
|
45
|
-
if fingerprints.is_file():
|
|
46
|
-
assert (
|
|
47
|
-
json.loads(fingerprints.read_text(encoding="utf-8"))["connector"] == FLEET
|
|
48
|
-
)
|
|
40
|
+
assert connector_name("immich_api") == FLEET
|
|
49
41
|
for module in sorted(PACKAGE.glob("*.py")):
|
|
50
42
|
assert all(name == FLEET for name in _call_connectors(module)), module.name
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Native SDK content and preset contracts; provider and engine boundaries are faked."""
|
|
2
|
+
|
|
3
|
+
import importlib.util
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from immich_api.mcp_server import build_server
|
|
8
|
+
|
|
9
|
+
ROOT = Path(__file__).parents[1]
|
|
10
|
+
PACKAGE = ROOT / "immich_api"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_generated_structure_is_fresh_and_reference_backed():
|
|
14
|
+
spec = importlib.util.spec_from_file_location(
|
|
15
|
+
"generate_immich_content", ROOT / "scripts/generate_immich_content.py"
|
|
16
|
+
)
|
|
17
|
+
module = importlib.util.module_from_spec(spec)
|
|
18
|
+
spec.loader.exec_module(module)
|
|
19
|
+
for path, text in module.artifacts().items():
|
|
20
|
+
assert path.read_text() == text
|
|
21
|
+
provenance = json.loads((PACKAGE / "ontology/schema-provenance.json").read_text())
|
|
22
|
+
assert len({item["class"] for item in provenance["properties"]}) == 8
|
|
23
|
+
relations = [
|
|
24
|
+
item
|
|
25
|
+
for item in provenance["properties"]
|
|
26
|
+
if not item["range"].startswith("xsd:")
|
|
27
|
+
]
|
|
28
|
+
assert len(relations) == 6
|
|
29
|
+
assert not any("contains" in item["property"].lower() for item in relations)
|
|
30
|
+
assert not any(
|
|
31
|
+
item["source_pointer"].endswith("/email") for item in provenance["properties"]
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_domain_registrar_retains_sdk_toggle(monkeypatch):
|
|
36
|
+
from agent_connector_sdk.mcp.tool_surface import registered_tools
|
|
37
|
+
|
|
38
|
+
monkeypatch.setenv("MCP_FLEET_REGISTRATION", "false")
|
|
39
|
+
monkeypatch.setenv("ALBUMSTOOL", "false")
|
|
40
|
+
server = build_server(command_args=["--transport", "stdio", "--auth-type", "none"])
|
|
41
|
+
tools = registered_tools(server)
|
|
42
|
+
assert "albums_operations" not in tools
|
|
43
|
+
assert "server_operations" in tools
|
|
44
|
+
assert "server" in tools["server_operations"].tags
|
|
@@ -4,7 +4,6 @@ import asyncio
|
|
|
4
4
|
from types import SimpleNamespace
|
|
5
5
|
|
|
6
6
|
import pytest
|
|
7
|
-
from agent_connector_sdk.ingest.request import build_request
|
|
8
7
|
from epistemic_graph.generated.source_ingestion import SourceIngestionMode
|
|
9
8
|
|
|
10
9
|
from immich_api import kg_ingest
|
|
@@ -103,32 +102,3 @@ def test_sdk_privacy_redaction_of_identity_refuses_before_submit():
|
|
|
103
102
|
)
|
|
104
103
|
)
|
|
105
104
|
assert not fake.calls
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def test_sdk_wire_payload_uses_actual_ontology_predicates():
|
|
109
|
-
import json
|
|
110
|
-
from pathlib import Path
|
|
111
|
-
|
|
112
|
-
fake = FakeIngest()
|
|
113
|
-
asyncio.run(
|
|
114
|
-
kg_ingest.ingest_album_metadata(
|
|
115
|
-
[album()], source_scope="fixture.account", ingest=fake
|
|
116
|
-
)
|
|
117
|
-
)
|
|
118
|
-
binding, changes = fake.calls[0]
|
|
119
|
-
request = build_request(binding, changes, previous=None)
|
|
120
|
-
assert request.mode is SourceIngestionMode.DELTA
|
|
121
|
-
assert request.authoritative_live_ids is None and request.withdrawals == []
|
|
122
|
-
record = request.records[0]
|
|
123
|
-
assert record.stream == binding.stream
|
|
124
|
-
assert record.payload["immichAlbumId"] == album()["id"]
|
|
125
|
-
assert record.payload["immichAlbumAlbumName"] == album()["albumName"]
|
|
126
|
-
assert "id" not in record.payload and "albumName" not in record.payload
|
|
127
|
-
root = Path(__file__).parents[1] / "immich_api"
|
|
128
|
-
manifest = json.loads((root / "connector_manifest.yml").read_text())
|
|
129
|
-
declared = manifest["schema_mappings"]["ImmichAlbum"]["fields"]
|
|
130
|
-
assert set(record.payload) <= set(declared)
|
|
131
|
-
assert manifest["identity"]["id_field"]["ImmichAlbum"] == "immichAlbumId"
|
|
132
|
-
shapes = (root / "ontology/shapes/immich.ttl").read_text()
|
|
133
|
-
assert all("sh:path :" + key + " " in shapes for key in record.payload)
|
|
134
|
-
assert record.mapping_reference == "manifest:immich#schema_mappings/ImmichAlbum"
|