refactor: restructure the agent package and add contributor docs #20

Merged
Jc-965 merged 20 commits from repo-restructure into main 2026-09-26 18:22:09 +00:00
Member

Summary

This pull request restructures the agent repository. The code moved from a flat agent/ directory into a src/cmugpt package, with large modules split by responsibility, configuration centralized, and tests moved to pytest. The production startup check, which had never been active, is now turned on. Comments, docstrings, and the README have been rewritten, and the repository now has a contributing guide and PR template. The service behaves the same as before. Closes #21.

Changes

Package layout

  • The code is now a src/cmugpt package installed as cmugpt-agent, with the entry point defined in pyproject.toml.
  • The 1,000-line memory module becomes a memory/ package with separate modules for the store, facts, the remember and forget tools, background extraction, and management routes.
  • The map code becomes a maps/ package, and buildings.json moves inside it so the built wheel ships the catalog.
  • The HTTP layer becomes an api/ package, with the app assembly in server.py, the shared bearer-token and body-size checks in deps.py, and one router per route group.
  • Per-turn tool and memory selection is split out of graph.py into planning.py. A new llm.py builds the OpenRouter clients in one place and caches them per configuration.
  • The package init is empty, so importing one module no longer loads the whole agent.

Configuration

  • All environment variables are read through settings.py, which uses pydantic-settings and builds a fresh object per call so tests can override values per case.
  • The prod secretspec profile now sets AGENT_ENV=production. The startup check for DATABASE_URL and a 32-character AGENT_SHARED_SECRET was already in the code but never ran.
  • The default local port is 5055, which avoids the AirPlay conflict on macOS. Kennel injects its own port in production.
  • A .env.example documents every variable with its default.

Tests

  • The unit tests move from ci_test/ to tests/unit/ and run under pytest with asyncio in auto mode. CI runs them with a single uv run pytest.
  • The live end-to-end checks move from tools/ to evals/ as pytest tests. They skip themselves when the API keys are absent and fail on a miss instead of printing a report.

Cleanup

  • The Procfile is removed, since Kennel never read it, along with a duplicate output name in flake.nix and a dangling pre-commit symlink.
  • The unused mcp, openai, and pre-commit dependencies are removed. Both libraries still arrive through the LangChain packages.
  • Two uncalled functions, a duplicated constant, three one-line settings wrappers, and four unused package exports are removed.

Code quality

  • Every function signature is annotated, and helpers used only inside their module are underscore-prefixed.
  • ruff now runs the pep8-naming rules and the PEP 257 docstring form checks, and the code passes both. DailyTokenLimitExceeded is renamed to DailyTokenLimitError.
  • Comments and docstrings across the package are rewritten to state contracts and reasons rather than narrate the code.

Documentation

  • The README is rewritten to cover the structure of the codebase and development process.
  • CONTRIBUTING.md covers the workflow, code style, commit conventions, and the pull request process.
  • AI tool state directories are gitignored.

AI use

  • None
  • Minor: autocomplete or suggestions for a few lines
  • Some: AI drafted parts of the change, the rest was written by hand
  • Most: AI wrote the bulk of the change, edited by hand
  • All: AI wrote the whole change, reviewed and tested by hand

Checklist

  • DATABASE_URL="" uv run pytest passes
  • uv run pytest evals run, if prompts or tool selection changed (prompts unchanged; the two smoke evals were run and pass)
  • Hooks pass (ruff and ty directly; devenv unavailable locally)
  • README updated if a variable, route, or command changed
  • No secrets, keys, or .env values in the diff
  • Commits follow Conventional Commits, one change each, rebased onto main
  • Title written like a commit subject
## Summary This pull request restructures the agent repository. The code moved from a flat `agent/` directory into a `src/cmugpt` package, with large modules split by responsibility, configuration centralized, and tests moved to pytest. The production startup check, which had never been active, is now turned on. Comments, docstrings, and the README have been rewritten, and the repository now has a contributing guide and PR template. The service behaves the same as before. Closes #21. ## Changes Package layout - The code is now a `src/cmugpt` package installed as `cmugpt-agent`, with the entry point defined in `pyproject.toml`. - The 1,000-line memory module becomes a `memory/` package with separate modules for the store, facts, the remember and forget tools, background extraction, and management routes. - The map code becomes a `maps/` package, and `buildings.json` moves inside it so the built wheel ships the catalog. - The HTTP layer becomes an `api/` package, with the app assembly in `server.py`, the shared bearer-token and body-size checks in `deps.py`, and one router per route group. - Per-turn tool and memory selection is split out of `graph.py` into `planning.py`. A new `llm.py` builds the OpenRouter clients in one place and caches them per configuration. - The package init is empty, so importing one module no longer loads the whole agent. Configuration - All environment variables are read through `settings.py`, which uses pydantic-settings and builds a fresh object per call so tests can override values per case. - The `prod` secretspec profile now sets `AGENT_ENV=production`. The startup check for `DATABASE_URL` and a 32-character `AGENT_SHARED_SECRET` was already in the code but never ran. - The default local port is 5055, which avoids the AirPlay conflict on macOS. Kennel injects its own port in production. - A `.env.example` documents every variable with its default. Tests - The unit tests move from `ci_test/` to `tests/unit/` and run under pytest with asyncio in auto mode. CI runs them with a single `uv run pytest`. - The live end-to-end checks move from `tools/` to `evals/` as pytest tests. They skip themselves when the API keys are absent and fail on a miss instead of printing a report. Cleanup - The Procfile is removed, since Kennel never read it, along with a duplicate output name in `flake.nix` and a dangling pre-commit symlink. - The unused `mcp`, `openai`, and `pre-commit` dependencies are removed. Both libraries still arrive through the LangChain packages. - Two uncalled functions, a duplicated constant, three one-line settings wrappers, and four unused package exports are removed. Code quality - Every function signature is annotated, and helpers used only inside their module are underscore-prefixed. - ruff now runs the pep8-naming rules and the PEP 257 docstring form checks, and the code passes both. `DailyTokenLimitExceeded` is renamed to `DailyTokenLimitError`. - Comments and docstrings across the package are rewritten to state contracts and reasons rather than narrate the code. Documentation - The README is rewritten to cover the structure of the codebase and development process. - `CONTRIBUTING.md` covers the workflow, code style, commit conventions, and the pull request process. - AI tool state directories are gitignored. ## AI use - [ ] None - [ ] Minor: autocomplete or suggestions for a few lines - [ ] Some: AI drafted parts of the change, the rest was written by hand - [x] Most: AI wrote the bulk of the change, edited by hand - [ ] All: AI wrote the whole change, reviewed and tested by hand ## Checklist - [x] `DATABASE_URL="" uv run pytest` passes - [x] `uv run pytest evals` run, if prompts or tool selection changed (prompts unchanged; the two smoke evals were run and pass) - [x] Hooks pass (ruff and ty directly; devenv unavailable locally) - [x] README updated if a variable, route, or command changed - [x] No secrets, keys, or `.env` values in the diff - [x] Commits follow Conventional Commits, one change each, rebased onto `main` - [x] Title written like a commit subject
docs: add contributing guide and rewrite readme
Some checks failed
kennel/build build succeeded
kennel/deploy provisioning declared resource 'postgres' failed: psql failed [GRANT CREATE ON DATABASE "kennel_019eb450_7be8_7972_9b42_2b14b425c92d_pr_20" TO "kennel_019eb450_7be8_7972_9b42_2b14b425c92d_pr_20_owner"]: ERROR: database "kennel_019eb450_7be8_7972_9b42_2b14b425c92d_pr_20" does not exist
CI / check-1 (pull_request) Failing after 8m16s
CI / build (pull_request) Successful in 10m11s
CI / check (pull_request) Failing after 0s
CI / test-agent (pull_request) Has been skipped
a0d21edd81
build: upgrade anyio to 4.14.2 for security advisories
Some checks failed
kennel/build build succeeded
kennel/deploy provisioning declared resource 'postgres' failed: psql failed [GRANT CREATE ON DATABASE "kennel_019eb450_7be8_7972_9b42_2b14b425c92d_pr_20" TO "kennel_019eb450_7be8_7972_9b42_2b14b425c92d_pr_20_owner"]: ERROR: database "kennel_019eb450_7be8_7972_9b42_2b14b425c92d_pr_20" does not exist
CI / build (pull_request) Successful in 2m2s
CI / check-1 (pull_request) Successful in 2m6s
CI / check (pull_request) Successful in 0s
CI / test-agent (pull_request) Successful in 48s
f0d87dbd94
Member

@thesuperRL Why is this issue happening? Is it because @Jc-965 doesn't have the right permissions? Grafana isn't very informative, would like to know what the cause is.

CC: @jiyas

@thesuperRL Why is this issue happening? Is it because @Jc-965 doesn't have the right permissions? Grafana isn't very informative, would like to know what the cause is. CC: @jiyas
Owner

@krishsax wrote in #20 (comment):

@thesuperRL Why is this issue happening? Is it because @Jc-965 doesn't have the right permissions? Grafana isn't very informative, would like to know what the cause is.

CC: @jiyas

It's a postgres issue I've seen a couple of times, just that you don't have correct perms on the relevant kennel job for some reason. I'll take a look during work session.

lowk thought i resolved it but i guess not

@krishsax wrote in https://git.cmu.dev/ScottyLabs/cmugpt-agent/pulls/20#issuecomment-11342: > @thesuperRL Why is this issue happening? Is it because @Jc-965 doesn't have the right permissions? Grafana isn't very informative, would like to know what the cause is. > > CC: @jiyas It's a postgres issue I've seen a couple of times, just that you don't have correct perms on the relevant kennel job for some reason. I'll take a look during work session. lowk thought i resolved it but i guess not
docs: setting up devenv
Some checks failed
kennel/build build succeeded
kennel/deploy provisioning declared resource 'postgres' failed: psql failed [GRANT CREATE ON DATABASE "kennel_019eb450_7be8_7972_9b42_2b14b425c92d_pr_20" TO "kennel_019eb450_7be8_7972_9b42_2b14b425c92d_pr_20_owner"]: ERROR: database "kennel_019eb450_7be8_7972_9b42_2b14b425c92d_pr_20" does not exist
CI / check-1 (pull_request) Successful in 1m45s
CI / build (pull_request) Successful in 2m9s
CI / check (pull_request) Successful in 0s
CI / test-agent (pull_request) Successful in 54s
0db8cb3380
Jc-965 merged commit eb77a23158 into main 2026-09-26 18:22:09 +00:00
Sign in to join this conversation.
No description provided.