kestrel-agent 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.
- kestrel_agent-0.1.0/.env.example +18 -0
- kestrel_agent-0.1.0/.github/workflows/ci.yml +41 -0
- kestrel_agent-0.1.0/.github/workflows/publish.yml +56 -0
- kestrel_agent-0.1.0/.gitignore +49 -0
- kestrel_agent-0.1.0/CHANGELOG.md +58 -0
- kestrel_agent-0.1.0/CONTRIBUTING.md +118 -0
- kestrel_agent-0.1.0/LICENSE +661 -0
- kestrel_agent-0.1.0/NOTICE +21 -0
- kestrel_agent-0.1.0/PKG-INFO +143 -0
- kestrel_agent-0.1.0/PRIVACY.md +44 -0
- kestrel_agent-0.1.0/README.md +95 -0
- kestrel_agent-0.1.0/SECURITY.md +76 -0
- kestrel_agent-0.1.0/docs/assets/README.md +65 -0
- kestrel_agent-0.1.0/docs/assets/kestrel-mark.png +0 -0
- kestrel_agent-0.1.0/docs/assets/kestrel-wordmark.png +0 -0
- kestrel_agent-0.1.0/profile.example.json +61 -0
- kestrel_agent-0.1.0/pyproject.toml +97 -0
- kestrel_agent-0.1.0/scripts/dogfood_agent_transcript.py +1042 -0
- kestrel_agent-0.1.0/src/kestrel/__init__.py +4 -0
- kestrel_agent-0.1.0/src/kestrel/__main__.py +6 -0
- kestrel_agent-0.1.0/src/kestrel/agent_protocol.py +1544 -0
- kestrel_agent-0.1.0/src/kestrel/apply/__init__.py +2 -0
- kestrel_agent-0.1.0/src/kestrel/apply/chrome.py +351 -0
- kestrel_agent-0.1.0/src/kestrel/apply/claude.py +129 -0
- kestrel_agent-0.1.0/src/kestrel/apply/dashboard.py +226 -0
- kestrel_agent-0.1.0/src/kestrel/apply/droid.py +253 -0
- kestrel_agent-0.1.0/src/kestrel/apply/engines.py +218 -0
- kestrel_agent-0.1.0/src/kestrel/apply/eventlog.py +113 -0
- kestrel_agent-0.1.0/src/kestrel/apply/launcher.py +1511 -0
- kestrel_agent-0.1.0/src/kestrel/apply/planning.py +330 -0
- kestrel_agent-0.1.0/src/kestrel/apply/prompt.py +706 -0
- kestrel_agent-0.1.0/src/kestrel/cli.py +1302 -0
- kestrel_agent-0.1.0/src/kestrel/config/employers.yaml +128 -0
- kestrel_agent-0.1.0/src/kestrel/config/searches.example.yaml +123 -0
- kestrel_agent-0.1.0/src/kestrel/config/sites.yaml +181 -0
- kestrel_agent-0.1.0/src/kestrel/config.py +568 -0
- kestrel_agent-0.1.0/src/kestrel/database.py +1561 -0
- kestrel_agent-0.1.0/src/kestrel/discovery/__init__.py +1 -0
- kestrel_agent-0.1.0/src/kestrel/discovery/composio.py +606 -0
- kestrel_agent-0.1.0/src/kestrel/discovery/filters.py +64 -0
- kestrel_agent-0.1.0/src/kestrel/discovery/jobspy.py +533 -0
- kestrel_agent-0.1.0/src/kestrel/discovery/salary.py +180 -0
- kestrel_agent-0.1.0/src/kestrel/discovery/smartextract.py +1102 -0
- kestrel_agent-0.1.0/src/kestrel/discovery/workday.py +564 -0
- kestrel_agent-0.1.0/src/kestrel/engine_auth.py +300 -0
- kestrel_agent-0.1.0/src/kestrel/enrichment/__init__.py +1 -0
- kestrel_agent-0.1.0/src/kestrel/enrichment/detail.py +983 -0
- kestrel_agent-0.1.0/src/kestrel/enrichment/remote.py +40 -0
- kestrel_agent-0.1.0/src/kestrel/enrichment/seniority.py +68 -0
- kestrel_agent-0.1.0/src/kestrel/llm.py +727 -0
- kestrel_agent-0.1.0/src/kestrel/onboarding.py +2406 -0
- kestrel_agent-0.1.0/src/kestrel/pipeline.py +707 -0
- kestrel_agent-0.1.0/src/kestrel/portal/__init__.py +10 -0
- kestrel_agent-0.1.0/src/kestrel/portal/app.py +1863 -0
- kestrel_agent-0.1.0/src/kestrel/portal/assistant.py +188 -0
- kestrel_agent-0.1.0/src/kestrel/portal/auth.py +138 -0
- kestrel_agent-0.1.0/src/kestrel/portal/automation.py +552 -0
- kestrel_agent-0.1.0/src/kestrel/portal/queries.py +322 -0
- kestrel_agent-0.1.0/src/kestrel/portal/runner.py +618 -0
- kestrel_agent-0.1.0/src/kestrel/portal/settings.py +274 -0
- kestrel_agent-0.1.0/src/kestrel/portal/static/ext-sse.js +385 -0
- kestrel_agent-0.1.0/src/kestrel/portal/static/htmx.min.js +1 -0
- kestrel_agent-0.1.0/src/kestrel/portal/static/kestrel-dark.png +0 -0
- kestrel_agent-0.1.0/src/kestrel/portal/static/kestrel-mark.png +0 -0
- kestrel_agent-0.1.0/src/kestrel/portal/static/kestrel-mono.png +0 -0
- kestrel_agent-0.1.0/src/kestrel/portal/static/kestrel-wordmark.png +0 -0
- kestrel_agent-0.1.0/src/kestrel/portal/static/portal.css +1178 -0
- kestrel_agent-0.1.0/src/kestrel/portal/system_check.py +300 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/automation.html +15 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/base.html +39 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/dashboard.html +88 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/engine.html +13 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/jobs.html +86 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/login.html +26 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/onboarding.html +11 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/assistant_panel.html +16 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/automation_cards.html +98 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/board_view_params.html +15 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/engine_gates.html +76 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/events.html +9 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/fit_assessment.html +27 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/job_card.html +95 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/job_detail.html +111 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/job_missing.html +3 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/jobs_board.html +60 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/jobs_progress.html +5 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/onboarding_chat.html +397 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/onboarding_surface.html +120 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/runs_table.html +31 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/system_checks.html +18 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/partials/workers.html +22 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/preview.html +36 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/run_log.html +24 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/runs.html +21 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/settings.html +88 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/system_check.html +22 -0
- kestrel_agent-0.1.0/src/kestrel/portal/templates/versions.html +53 -0
- kestrel_agent-0.1.0/src/kestrel/scoring/__init__.py +2 -0
- kestrel_agent-0.1.0/src/kestrel/scoring/cover_letter.py +359 -0
- kestrel_agent-0.1.0/src/kestrel/scoring/docs.py +60 -0
- kestrel_agent-0.1.0/src/kestrel/scoring/pdf.py +619 -0
- kestrel_agent-0.1.0/src/kestrel/scoring/scorer.py +419 -0
- kestrel_agent-0.1.0/src/kestrel/scoring/tailor.py +683 -0
- kestrel_agent-0.1.0/src/kestrel/scoring/validator.py +475 -0
- kestrel_agent-0.1.0/src/kestrel/security.py +44 -0
- kestrel_agent-0.1.0/src/kestrel/view.py +413 -0
- kestrel_agent-0.1.0/src/kestrel/wizard/__init__.py +1 -0
- kestrel_agent-0.1.0/src/kestrel/wizard/init.py +529 -0
- kestrel_agent-0.1.0/tests/__init__.py +0 -0
- kestrel_agent-0.1.0/tests/conftest.py +216 -0
- kestrel_agent-0.1.0/tests/e2e/__init__.py +0 -0
- kestrel_agent-0.1.0/tests/e2e/conftest.py +196 -0
- kestrel_agent-0.1.0/tests/e2e/test_automation.py +226 -0
- kestrel_agent-0.1.0/tests/e2e/test_full_journey.py +385 -0
- kestrel_agent-0.1.0/tests/e2e/test_jobs_board.py +235 -0
- kestrel_agent-0.1.0/tests/e2e/test_onboarding_wizard.py +404 -0
- kestrel_agent-0.1.0/tests/e2e/test_smoke.py +36 -0
- kestrel_agent-0.1.0/tests/e2e/test_system_check.py +44 -0
- kestrel_agent-0.1.0/tests/test_agent_apply_verbs.py +412 -0
- kestrel_agent-0.1.0/tests/test_agent_coexistence.py +206 -0
- kestrel_agent-0.1.0/tests/test_agent_journey.py +278 -0
- kestrel_agent-0.1.0/tests/test_agent_materials.py +509 -0
- kestrel_agent-0.1.0/tests/test_agent_protocol.py +549 -0
- kestrel_agent-0.1.0/tests/test_agent_scoring.py +428 -0
- kestrel_agent-0.1.0/tests/test_apply_guardrails.py +414 -0
- kestrel_agent-0.1.0/tests/test_apply_loop_bugs.py +427 -0
- kestrel_agent-0.1.0/tests/test_apply_prompt_truthfulness.py +231 -0
- kestrel_agent-0.1.0/tests/test_apply_status_writers.py +498 -0
- kestrel_agent-0.1.0/tests/test_audit_r3_deferred_data.py +415 -0
- kestrel_agent-0.1.0/tests/test_audit_r3_deferred_protocol.py +510 -0
- kestrel_agent-0.1.0/tests/test_audit_r3_protocol_remediation.py +616 -0
- kestrel_agent-0.1.0/tests/test_audit_r3_remediation.py +766 -0
- kestrel_agent-0.1.0/tests/test_audit_wave2_f3_f4.py +155 -0
- kestrel_agent-0.1.0/tests/test_chrome_clone.py +109 -0
- kestrel_agent-0.1.0/tests/test_cli_entry_point.py +47 -0
- kestrel_agent-0.1.0/tests/test_cli_json_output.py +222 -0
- kestrel_agent-0.1.0/tests/test_composio_discovery.py +697 -0
- kestrel_agent-0.1.0/tests/test_deep_filter_layer1.py +483 -0
- kestrel_agent-0.1.0/tests/test_document_history.py +437 -0
- kestrel_agent-0.1.0/tests/test_engine_auth.py +470 -0
- kestrel_agent-0.1.0/tests/test_engine_selection.py +788 -0
- kestrel_agent-0.1.0/tests/test_file_permissions.py +121 -0
- kestrel_agent-0.1.0/tests/test_infra_attempt_budget.py +159 -0
- kestrel_agent-0.1.0/tests/test_jobs_board_filters.py +387 -0
- kestrel_agent-0.1.0/tests/test_jobs_board_nav.py +282 -0
- kestrel_agent-0.1.0/tests/test_jobs_cards.py +139 -0
- kestrel_agent-0.1.0/tests/test_jobs_filter_cli.py +451 -0
- kestrel_agent-0.1.0/tests/test_jobs_rerank.py +485 -0
- kestrel_agent-0.1.0/tests/test_jobs_verbs.py +278 -0
- kestrel_agent-0.1.0/tests/test_launcher_url_escape.py +111 -0
- kestrel_agent-0.1.0/tests/test_llm_gemini_header.py +69 -0
- kestrel_agent-0.1.0/tests/test_llm_probe.py +222 -0
- kestrel_agent-0.1.0/tests/test_llm_retry_cap.py +112 -0
- kestrel_agent-0.1.0/tests/test_model_dropdown.py +415 -0
- kestrel_agent-0.1.0/tests/test_onboarding_agent.py +766 -0
- kestrel_agent-0.1.0/tests/test_onboarding_choices.py +1025 -0
- kestrel_agent-0.1.0/tests/test_onboarding_prefill.py +639 -0
- kestrel_agent-0.1.0/tests/test_pdf_busy_loop.py +398 -0
- kestrel_agent-0.1.0/tests/test_pipeline_bugs.py +898 -0
- kestrel_agent-0.1.0/tests/test_portal_auth.py +192 -0
- kestrel_agent-0.1.0/tests/test_portal_automation.py +634 -0
- kestrel_agent-0.1.0/tests/test_portal_automation_ui.py +626 -0
- kestrel_agent-0.1.0/tests/test_portal_engine_gate.py +368 -0
- kestrel_agent-0.1.0/tests/test_portal_onboarding.py +331 -0
- kestrel_agent-0.1.0/tests/test_portal_pages.py +355 -0
- kestrel_agent-0.1.0/tests/test_portal_revamp.py +279 -0
- kestrel_agent-0.1.0/tests/test_portal_runner.py +480 -0
- kestrel_agent-0.1.0/tests/test_portal_settings.py +285 -0
- kestrel_agent-0.1.0/tests/test_portal_sse.py +249 -0
- kestrel_agent-0.1.0/tests/test_portal_system_check.py +320 -0
- kestrel_agent-0.1.0/tests/test_prompt_security.py +217 -0
- kestrel_agent-0.1.0/tests/test_provider_selection.py +428 -0
- kestrel_agent-0.1.0/tests/test_remote_flag.py +115 -0
- kestrel_agent-0.1.0/tests/test_rename_migration.py +204 -0
- kestrel_agent-0.1.0/tests/test_resume_upload_paths.py +159 -0
- kestrel_agent-0.1.0/tests/test_salary_bands.py +250 -0
- kestrel_agent-0.1.0/tests/test_scoring_rescore.py +406 -0
- kestrel_agent-0.1.0/tests/test_scoring_validator.py +130 -0
- kestrel_agent-0.1.0/tests/test_security_redaction.py +67 -0
- kestrel_agent-0.1.0/tests/test_smoke.py +51 -0
- kestrel_agent-0.1.0/tests/test_zero_terminal_copy.py +171 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Kestrel Environment Configuration
|
|
2
|
+
# Copy to ~/.kestrel/.env and fill in your values.
|
|
3
|
+
|
|
4
|
+
# LLM Provider (pick one)
|
|
5
|
+
GEMINI_API_KEY= # Gemini 2.0 Flash (recommended, cheapest)
|
|
6
|
+
# OPENAI_API_KEY= # OpenAI (GPT-4o-mini)
|
|
7
|
+
# LLM_URL=http://127.0.0.1:8080/v1 # Local LLM (llama.cpp, Ollama)
|
|
8
|
+
# LLM_MODEL= # Override model name
|
|
9
|
+
|
|
10
|
+
# Auto-Apply (optional)
|
|
11
|
+
CAPSOLVER_API_KEY= # For CAPTCHA solving during auto-apply
|
|
12
|
+
|
|
13
|
+
# Auto-Apply engine (optional; default: claude)
|
|
14
|
+
# AUTOAPPLY_ENGINE=droid # claude | droid
|
|
15
|
+
# FACTORY_API_KEY= # Required when the engine is droid (child env only)
|
|
16
|
+
|
|
17
|
+
# Proxy (optional, for scraping)
|
|
18
|
+
# PROXY=host:port:user:pass
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
test:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Checkout
|
|
23
|
+
uses: actions/checkout@v4
|
|
24
|
+
|
|
25
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: ${{ matrix.python-version }}
|
|
29
|
+
cache: pip
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: pip install -e ".[dev]"
|
|
33
|
+
|
|
34
|
+
- name: Install Playwright Chromium
|
|
35
|
+
run: playwright install --with-deps chromium
|
|
36
|
+
|
|
37
|
+
- name: Lint
|
|
38
|
+
run: ruff check .
|
|
39
|
+
|
|
40
|
+
- name: Test
|
|
41
|
+
run: pytest -v
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Publish kestrel-agent to PyPI on version tags (v*), via OIDC trusted publishing.
|
|
2
|
+
#
|
|
3
|
+
# MANUAL SETUP REQUIRED BEFORE THE FIRST TAG (release runbook):
|
|
4
|
+
#
|
|
5
|
+
# 1. The PyPI project `kestrel-agent` must be registered before the first
|
|
6
|
+
# publication. Registration happens on first upload — but with trusted
|
|
7
|
+
# publishing, the project must instead be pre-created on PyPI with the
|
|
8
|
+
# pending publisher configured (PyPI -> Publishing -> add a pending
|
|
9
|
+
# trusted publisher), because a tag-triggered workflow cannot claim an
|
|
10
|
+
# unregistered project name without a human in the loop.
|
|
11
|
+
# 2. Configure the trusted-publisher entry on PyPI for
|
|
12
|
+
# `Vontarius-Ventures/kestrel`:
|
|
13
|
+
# - owner: Vontarius-Ventures
|
|
14
|
+
# - repository: kestrel
|
|
15
|
+
# - workflow name: publish.yml
|
|
16
|
+
# - environment: pypi
|
|
17
|
+
# (Note the repository name is `kestrel`, while this file lives in the
|
|
18
|
+
# private repo `VontariusF/ApplyPilot` until the public cut; the entry
|
|
19
|
+
# must point at the public repo.)
|
|
20
|
+
# 3. The `pypi` GitHub environment must exist on the target repo with the
|
|
21
|
+
# OIDC id-token permission (granted here via `permissions.id-token`).
|
|
22
|
+
#
|
|
23
|
+
# Kestrel is an AGPL-3.0 fork of Pickle-Pixel/ApplyPilot; see NOTICE and
|
|
24
|
+
# README for upstream attribution.
|
|
25
|
+
|
|
26
|
+
name: Publish kestrel-agent to PyPI
|
|
27
|
+
|
|
28
|
+
on:
|
|
29
|
+
push:
|
|
30
|
+
tags:
|
|
31
|
+
- "v*"
|
|
32
|
+
|
|
33
|
+
jobs:
|
|
34
|
+
publish:
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
environment: pypi
|
|
37
|
+
permissions:
|
|
38
|
+
id-token: write # required for OIDC trusted publishing
|
|
39
|
+
|
|
40
|
+
steps:
|
|
41
|
+
- name: Checkout
|
|
42
|
+
uses: actions/checkout@v4
|
|
43
|
+
|
|
44
|
+
- name: Set up Python
|
|
45
|
+
uses: actions/setup-python@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: "3.12"
|
|
48
|
+
|
|
49
|
+
- name: Install build tools
|
|
50
|
+
run: pip install build
|
|
51
|
+
|
|
52
|
+
- name: Build kestrel-agent distribution
|
|
53
|
+
run: python -m build
|
|
54
|
+
|
|
55
|
+
- name: Publish kestrel-agent to PyPI
|
|
56
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# User data (NEVER commit)
|
|
2
|
+
profile.json
|
|
3
|
+
resume.txt
|
|
4
|
+
resume.pdf
|
|
5
|
+
*.env
|
|
6
|
+
.env.*
|
|
7
|
+
!.env.example
|
|
8
|
+
|
|
9
|
+
# Runtime artifacts
|
|
10
|
+
*.db
|
|
11
|
+
tailored_resumes/
|
|
12
|
+
cover_letters/
|
|
13
|
+
chrome-workers/
|
|
14
|
+
apply-workers/
|
|
15
|
+
apply_logs/
|
|
16
|
+
logs/
|
|
17
|
+
|
|
18
|
+
# MCP configs (per-machine)
|
|
19
|
+
.mcp*.json
|
|
20
|
+
|
|
21
|
+
# Python
|
|
22
|
+
__pycache__/
|
|
23
|
+
*.py[cod]
|
|
24
|
+
*$py.class
|
|
25
|
+
*.egg-info/
|
|
26
|
+
dist/
|
|
27
|
+
build/
|
|
28
|
+
*.egg
|
|
29
|
+
|
|
30
|
+
# IDE
|
|
31
|
+
.vscode/
|
|
32
|
+
.idea/
|
|
33
|
+
*.swp
|
|
34
|
+
*.swo
|
|
35
|
+
|
|
36
|
+
# OS
|
|
37
|
+
.DS_Store
|
|
38
|
+
Thumbs.db
|
|
39
|
+
|
|
40
|
+
# Owner secrets (never ship or commit)
|
|
41
|
+
*.local
|
|
42
|
+
.env*.local
|
|
43
|
+
|
|
44
|
+
# Local SQLite databases (never commit)
|
|
45
|
+
*.sqlite3
|
|
46
|
+
*.sqlite3-journal
|
|
47
|
+
|
|
48
|
+
# Claude Code
|
|
49
|
+
.claude/
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Kestrel will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-11-09
|
|
9
|
+
|
|
10
|
+
First public release of Kestrel, the open-source job-search and application
|
|
11
|
+
assistant.
|
|
12
|
+
|
|
13
|
+
### About
|
|
14
|
+
|
|
15
|
+
Kestrel helps candidates discover and evaluate jobs, prepare tailored
|
|
16
|
+
application materials, and manage applications through a human-supervised,
|
|
17
|
+
localhost-first workflow. This release is cut from a fresh versioning start:
|
|
18
|
+
`0.1.0` restarts the version lineage and this changelog begins anew.
|
|
19
|
+
|
|
20
|
+
### Lineage
|
|
21
|
+
|
|
22
|
+
Kestrel is a fork of [ApplyPilot](https://github.com/Pickle-Pixel/ApplyPilot)
|
|
23
|
+
by Pickle-Pixel, released under the GNU Affero General Public License
|
|
24
|
+
v3.0. Upstream copyright is retained; Kestrel's changes continue to be
|
|
25
|
+
distributed under AGPL-3.0. See `LICENSE` and `NOTICE` for attribution
|
|
26
|
+
details.
|
|
27
|
+
|
|
28
|
+
### Added (carried from the fork)
|
|
29
|
+
|
|
30
|
+
- 6-stage pipeline: discover, enrich, score, tailor, cover letter, apply
|
|
31
|
+
- Multi-source job discovery: Indeed, LinkedIn, Glassdoor, ZipRecruiter, Google Jobs
|
|
32
|
+
- Workday employer portal support with a preconfigured employer registry
|
|
33
|
+
- Direct career site scraping with a 3-tier extraction cascade
|
|
34
|
+
(JSON-LD, CSS selectors, AI fallback)
|
|
35
|
+
- AI-powered job scoring (1-10 fit scale with rationale) and composable
|
|
36
|
+
filters with reranking and score history
|
|
37
|
+
- Resume tailoring with factual preservation (no fabrication) and
|
|
38
|
+
per-job cover letter generation
|
|
39
|
+
- Autonomous browser-based application submission via Playwright, with
|
|
40
|
+
plan-then-confirm controls, attempt limits, and human-gated submissions
|
|
41
|
+
- Typer-based CLI (`kestrel`), machine-readable `status --json` and
|
|
42
|
+
`doctor --json` output, and an agent-driven onboarding flow
|
|
43
|
+
- Optional single-user FastAPI portal (localhost, auth by default)
|
|
44
|
+
- Multi-provider LLM support (Gemini, OpenAI, local models via
|
|
45
|
+
OpenAI-compatible endpoints)
|
|
46
|
+
- Local SQLite storage under `~/.kestrel`
|
|
47
|
+
|
|
48
|
+
### Changed from upstream
|
|
49
|
+
|
|
50
|
+
- Package distribution and PyPI name: `kestrel-agent` (CLI: `kestrel`)
|
|
51
|
+
- Default data directory: `~/.kestrel` (migrates from `~/.applypilot`
|
|
52
|
+
on first run; `KESTREL_DIR` replaces `APPLYPILOT_DIR` with the legacy
|
|
53
|
+
variable still honored as a fallback)
|
|
54
|
+
- Environment namespace: `KESTREL_*` replaces `APPLYPILOT_*`, with legacy
|
|
55
|
+
fallbacks for compatibility
|
|
56
|
+
- Privacy: removed personal fixtures, machine-specific paths, and
|
|
57
|
+
internal transcripts; rebalanced the example employer registry toward a
|
|
58
|
+
geographically neutral sample
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Contributing to Kestrel
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to Kestrel — an AGPL-3.0 fork of
|
|
4
|
+
[Pickle-Pixel/ApplyPilot](https://github.com/Pickle-Pixel/ApplyPilot). This
|
|
5
|
+
guide covers development setup, the gates every change must pass, and the
|
|
6
|
+
ground rules for what never enters the repository.
|
|
7
|
+
|
|
8
|
+
## Development Setup
|
|
9
|
+
|
|
10
|
+
### Prerequisites
|
|
11
|
+
|
|
12
|
+
- Python 3.11 or higher
|
|
13
|
+
- Git
|
|
14
|
+
|
|
15
|
+
### Clone and Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
git clone https://github.com/Vontarius-Ventures/kestrel.git
|
|
19
|
+
cd kestrel
|
|
20
|
+
pip install -e ".[dev]"
|
|
21
|
+
playwright install chromium
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This installs Kestrel in editable mode with the development dependencies
|
|
25
|
+
(pytest, ruff, and the portal stack) and downloads the Chromium browser
|
|
26
|
+
binary for Playwright.
|
|
27
|
+
|
|
28
|
+
### Verify the installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
kestrel --version
|
|
32
|
+
kestrel doctor --json
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Must-pass gates
|
|
36
|
+
|
|
37
|
+
These must pass before you open a PR — CI runs them, and a red gate blocks
|
|
38
|
+
the merge:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
ruff check . # lint (src + tests)
|
|
42
|
+
pytest tests -m "not e2e" # unit suite (non-e2e)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
For portal or onboarding changes, also run the browser e2e suite
|
|
46
|
+
(`pytest tests/e2e`); Chromium must be installed once per machine
|
|
47
|
+
(`playwright install chromium`) — without it the e2e tests silently SKIP,
|
|
48
|
+
and a skipped gate is no gate.
|
|
49
|
+
|
|
50
|
+
## How to contribute
|
|
51
|
+
|
|
52
|
+
1. Check existing [issues](https://github.com/Vontarius-Ventures/kestrel/issues)
|
|
53
|
+
to avoid duplicating work; for new features, open an issue first to
|
|
54
|
+
discuss the approach.
|
|
55
|
+
2. Fork the repo and create a feature branch from `main`.
|
|
56
|
+
3. Write code with type hints and docstrings, and add tests for new
|
|
57
|
+
functionality — bug fixes need a regression test.
|
|
58
|
+
4. Run the must-pass gates above.
|
|
59
|
+
5. Submit a PR with a clear description of what changed and why.
|
|
60
|
+
|
|
61
|
+
### Adding Workday employers and career sites
|
|
62
|
+
|
|
63
|
+
Workday employer portals live in `src/kestrel/config/employers.yaml`; direct
|
|
64
|
+
career sites in `src/kestrel/config/sites.yaml`. Find the portal URL and
|
|
65
|
+
Workday instance/tenant (or the site's CSS selectors for job listings), add
|
|
66
|
+
an entry following the existing format, and verify with
|
|
67
|
+
`kestrel run --stage discover` against that employer or site before
|
|
68
|
+
submitting.
|
|
69
|
+
|
|
70
|
+
## Code style
|
|
71
|
+
|
|
72
|
+
- **Type hints** on all function signatures.
|
|
73
|
+
- **Docstrings** (Google style) on all public functions and classes.
|
|
74
|
+
- **snake_case** for functions and variables, **PascalCase** for classes.
|
|
75
|
+
- **Imports** sorted by Ruff (isort-compatible); **line length** 120
|
|
76
|
+
characters.
|
|
77
|
+
- Auto-fix what Ruff can fix: `ruff check src/ --fix`.
|
|
78
|
+
|
|
79
|
+
## Ground rules — never commit
|
|
80
|
+
|
|
81
|
+
These are hard rules, enforced by review; violations are removed on sight:
|
|
82
|
+
|
|
83
|
+
- **Keys, tokens, or credentials of any kind** — API keys, OAuth tokens,
|
|
84
|
+
session cookies, password files.
|
|
85
|
+
- **`.env*.local` and `*.local` files** — local-only configuration and
|
|
86
|
+
secrets stay on your machine. `.env.example` (placeholders only) is the
|
|
87
|
+
template that ships.
|
|
88
|
+
- **Personal machine details** — home-directory paths, hostnames, IPs,
|
|
89
|
+
usernames, deployed-service configs (e.g., launchd plists).
|
|
90
|
+
- **Local databases** — SQLite files and their journals.
|
|
91
|
+
- **Live resume/profile data** — `profile.json` and `resume.txt` are
|
|
92
|
+
git-ignored; commit only the `profile.example.json` / example fixtures.
|
|
93
|
+
|
|
94
|
+
## Project structure
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
kestrel/
|
|
98
|
+
├── src/kestrel/ # Main package
|
|
99
|
+
│ ├── cli.py # CLI entry points
|
|
100
|
+
│ ├── pipeline.py # Stage orchestration (tailor, cover letters, PDF)
|
|
101
|
+
│ ├── discovery/ # Stage 1: job discovery scrapers
|
|
102
|
+
│ ├── enrichment/ # Stage 2: description extraction
|
|
103
|
+
│ ├── scoring/ # Stage 3: AI scoring
|
|
104
|
+
│ ├── apply/ # Stage 6: browser automation (Claude/Droid engines)
|
|
105
|
+
│ ├── portal/ # Localhost web portal
|
|
106
|
+
│ ├── wizard/ # Onboarding wizard
|
|
107
|
+
│ ├── agent_protocol.py # Host-driven agent protocol (JSON verbs)
|
|
108
|
+
│ ├── database.py # SQLite store
|
|
109
|
+
│ └── config/ # Bundled YAML configs (employers, sites, searches)
|
|
110
|
+
├── tests/ # Test suite (unit + e2e)
|
|
111
|
+
└── pyproject.toml # Package configuration
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
By contributing to Kestrel, you agree that your contributions will be
|
|
117
|
+
licensed under the [GNU Affero General Public License v3.0](LICENSE).
|
|
118
|
+
Kestrel retains upstream ApplyPilot attribution per [NOTICE](NOTICE).
|