Commit Graph
20 Commits
Author SHA1 Message Date
LatteandClaude Opus 4.8 463ea84360 feat(sde): bulk-load downloader + offline system/station lookups
CI / lint (pull_request) Successful in 51s
CI / test (pull_request) Successful in 59s
CI / publish (pull_request) Has been skipped
CI / lint (push) Successful in 51s
CI / test (push) Successful in 58s
CI / publish (push) Successful in 51s
Implements issue #51. Adds a Fuzzwork SDE downloader/importer and
expands the offline lookup layer beyond item types.

- sde.py: SDE_URL constant (FAMILIAR_SDE_URL override) and
  async download_sde() that streams + bz2-decompresses the dump
  incrementally to sde_path(), resetting the cached connection.
- sde.py: system_by_id/system_by_name/station_by_id offline lookups,
  all degrading to None when the table/file is missing.
- universe.py: get_system/get_station prefer the SDE when available,
  falling back to ESI otherwise (signatures unchanged).
- __main__.py: `familiar sde download|status|path` subcommands.
- tests: download_sde via injected MockTransport, new lookups + None
  fallbacks, and SDE-vs-ESI fast-path/fallback for get_system/station.
- README: short offline-SDE setup note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 21:25:09 +02:00
LatteandClaude Opus 4.8 2f12a03257 feat(sde): optional local SDE store for offline name/type lookups
CI / lint (pull_request) Successful in 51s
CI / test (pull_request) Successful in 59s
CI / publish (pull_request) Has been skipped
CI / lint (push) Successful in 51s
CI / test (push) Successful in 58s
CI / publish (push) Successful in 50s
Add src/familiar/sde.py backing type lookups from a local SQLite SDE with
graceful fallback to ESI when absent. lookup.resolve_id prefers the SDE for
inventory_types; universe.get_item serves SDE-backed fields with no network
call. Register a read-only sde_status() MCP tool. Tested against an in-memory
SQLite fixture.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 20:44:18 +02:00
LatteandClaude Opus 4.8 0dfd6d2350 feat(writes): enable write actions by default (opt-out)
CI / lint (pull_request) Successful in 51s
CI / test (pull_request) Successful in 58s
CI / publish (pull_request) Has been skipped
CI / lint (push) Successful in 50s
CI / test (push) Successful in 57s
CI / publish (push) Successful in 51s
Invert the global write toggle so writes are ENABLED by default and the
user opts OUT, while keeping all other safety intact (per-call confirm=true
dry-run preview and the on-disk audit log are unchanged).

- writes.py: use a `writes_disabled` flag file instead of `writes_enabled`;
  `writes_enabled()` returns True unless the flag exists (env var still
  honored either way); `set_writes(False)` creates the flag, `set_writes(True)`
  removes it. Update user-facing notes.
- tests: default is now ENABLED; adjust toggle/disabled tests (set disabled
  explicitly via set_writes(False) or FAMILIAR_ENABLE_WRITES=0).
- README.md / CLAUDE.md: document writes are on by default, opt out via
  `familiar writes disable`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 20:39:25 +02:00
LatteandClaude Opus 4.8 0f7a861fc4 Phase 5: ESI Expires caching, error-limit back-off, setup docs (#16)
CI / lint (pull_request) Successful in 51s
CI / test (pull_request) Successful in 58s
CI / publish (pull_request) Has been skipped
CI / lint (push) Successful in 51s
CI / test (push) Successful in 58s
CI / publish (push) Successful in 51s
EsiClient now caches GET responses honoring the Expires header and backs off
when the rolling ESI error window is nearly exhausted (X-Esi-Error-Limit-*).
README gains Setup / Connect-to-Claude / enabling-writes sections.

Closes #16. SDE bulk-load split out to its own follow-up (#51).
135 tests, coverage 90%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 20:31:42 +02:00
LatteandClaude Opus 4.8 318ca17889 Phase 4: planetary interaction reads (#29)
CI / lint (pull_request) Successful in 51s
CI / test (pull_request) Successful in 58s
CI / publish (pull_request) Has been skipped
CI / lint (push) Successful in 51s
CI / test (push) Successful in 58s
CI / publish (push) Successful in 51s
Add read-only PI tools: get_planets (colonies), get_planet_layout
(pins/links/routes), get_corp_customs_offices. ESI exposes no PI write
endpoint despite the manage_planets scope name, so these are reads.

Closes #29. 132 tests, coverage 90%, 84 tools.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 20:22:35 +02:00
LatteandClaude Opus 4.8 0a828af4df Phase 4: fleet & UI commands — read + guarded writes (#27, #28)
CI / lint (pull_request) Successful in 51s
CI / publish (pull_request) Has been skipped
CI / test (pull_request) Successful in 57s
CI / lint (push) Successful in 51s
CI / test (push) Successful in 59s
CI / publish (push) Successful in 51s
Fleet: get_fleet (read, handles not-in-fleet); guarded invite_to_fleet and
update_fleet. UI: guarded set_waypoint and open_window (market/info/contract).
All writes go through write-safety.

Closes #27, #28. 128 tests, coverage 89%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 20:18:59 +02:00
LatteandClaude Opus 4.8 b3f06af8a4 Phase 4: contacts & fittings — reads + guarded writes (#25, #26)
CI / lint (pull_request) Successful in 50s
CI / test (pull_request) Successful in 57s
CI / publish (pull_request) Has been skipped
CI / lint (push) Successful in 50s
CI / test (push) Successful in 57s
CI / publish (push) Successful in 50s
Contacts: read character/corp/alliance contacts; guarded add/remove of
character contacts. Fittings: read saved fits; guarded create/delete.
EsiClient.delete now takes params. All writes go through write-safety.

Closes #25, #26. 120 tests, coverage 89%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 20:14:57 +02:00
LatteandClaude Opus 4.8 3bd170e8ab Phase 4: mail & calendar — reads + guarded writes (#23, #24)
CI / test (push) Successful in 56s
CI / lint (pull_request) Successful in 51s
CI / test (pull_request) Successful in 58s
CI / publish (pull_request) Has been skipped
CI / lint (push) Successful in 50s
CI / publish (push) Successful in 50s
Add read tools (get_mail, read_mail, get_calendar) and guarded write tools
(send_mail, set_mail_read, respond_calendar_event). Writes resolve an
explicit character, return a dry-run preview unless confirm=true, and only
execute when writes are enabled. Add EsiClient put/delete.

Closes #23, #24. 112 tests, coverage 90%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 20:11:07 +02:00
LatteandClaude Opus 4.8 f4f6ddede8 Phase 4: remaining reads — FW, projects, freelance, activities, access (#34,#35,#36)
CI / lint (pull_request) Successful in 51s
CI / test (pull_request) Successful in 57s
CI / publish (pull_request) Has been skipped
CI / lint (push) Successful in 50s
CI / test (push) Successful in 57s
CI / publish (push) Successful in 51s
Add read-only tools: faction-warfare stats (char + corp), freelance jobs
(char + corp), corp projects, character activities, and access lists.
FW endpoints are stable; the newer projects/freelance/activities/access
paths are best-effort and flagged for live confirmation.

Closes #34, #35, #36. 106 tests, coverage 91%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 20:07:02 +02:00
LatteandClaude Opus 4.8 20761d8644 Phase 4: corp economy & facilities reads (#33, #20)
CI / publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 50s
CI / test (pull_request) Successful in 57s
CI / lint (push) Successful in 51s
CI / test (push) Successful in 57s
CI / publish (push) Successful in 52s
Add read-only corp tools: wallets, assets, mining observers, facilities,
starbases — all corp-level (need corp roles). Closes #33 and completes the
remaining corp items of #20.

100 tests, coverage 91%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 20:03:42 +02:00
LatteandClaude Opus 4.8 754c80485a Phase 4: corp organization reads (#32)
CI / lint (pull_request) Successful in 51s
CI / test (pull_request) Successful in 56s
CI / publish (pull_request) Has been skipped
CI / lint (push) Successful in 51s
CI / test (push) Successful in 58s
CI / publish (push) Successful in 51s
Add read-only corp tools: members, member tracking, divisions, titles,
medals, standings (corp-level, need corp roles), plus the character's own
corp roles. Closes #32.

95 tests, coverage 91%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 20:00:36 +02:00
LatteandClaude Opus 4.8 ca393e3f86 Phase 4: character profile/social reads (#31)
CI / lint (pull_request) Successful in 50s
CI / test (pull_request) Successful in 57s
CI / publish (pull_request) Has been skipped
CI / lint (push) Successful in 50s
CI / test (push) Successful in 57s
CI / publish (push) Successful in 50s
Add read-only tools: loyalty points, standings, medals, titles, agents
research, jump fatigue, notifications, chat channels — per character or
aggregated. Closes #31.

90 tests, coverage 92%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 19:53:23 +02:00
LatteandClaude Opus 4.8 4203a907d5 Phase 4: killmails + zKillboard (read)
CI / lint (pull_request) Successful in 50s
CI / test (pull_request) Successful in 56s
CI / publish (pull_request) Has been skipped
CI / lint (push) Successful in 51s
CI / test (push) Successful in 57s
CI / publish (push) Successful in 50s
Add read-only killmail tools: recent character and corp killmails (refs
enriched with system/victim/attacker detail) plus zKillboard PvP stats via
a tiny injectable zkill client. New charutil.character_targets helper for
token-less per-character iteration.

85 tests, coverage 93%. Closes #30.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 19:42:07 +02:00
LatteandClaude Opus 4.8 07738f2237 Phase 4: write-action safety & guardrails (#22)
CI / lint (pull_request) Successful in 51s
CI / test (pull_request) Successful in 57s
CI / publish (pull_request) Has been skipped
CI / test (push) Successful in 57s
CI / lint (push) Successful in 51s
CI / publish (push) Successful in 50s
Add writes.py: the single gate every write tool must pass. A write happens
only when confirm=true AND writes are enabled (off by default); otherwise a
dry-run preview is returned. Every executed write is appended to an audit
log. New `familiar writes [enable|disable|status]` CLI and a read-only
write_status MCP tool.

81 tests, coverage 92%. Closes #22.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 19:37:37 +02:00
LatteandClaude Opus 4.8 692c8e245a Phase 3: structure tools (search, info, markets, container logs)
CI / lint (pull_request) Successful in 52s
CI / lint (push) Successful in 50s
CI / test (pull_request) Successful in 59s
CI / publish (pull_request) Has been skipped
CI / test (push) Successful in 56s
CI / publish (push) Successful in 51s
Add read-only structure tools: search_structures (per character),
get_structure and get_structure_market (single structure via one token),
and get_corp container logs. New charutil.one_token helper picks a single
authenticated token (named character or first).

31 tools total, 75 tests, coverage 92%. Closes #21.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 19:32:02 +02:00
LatteandClaude Opus 4.8 eeebfaa684 Phase 3: industry & trade tools (character + corp)
CI / lint (pull_request) Successful in 51s
CI / lint (push) Successful in 53s
CI / test (pull_request) Successful in 1m0s
CI / publish (pull_request) Has been skipped
CI / test (push) Successful in 58s
CI / publish (push) Successful in 51s
Add read-only industry tools (industry jobs, blueprints, mining ledger;
corp jobs + blueprints) and trade tools (contracts, own market orders;
corp contracts + orders). New charutil helper runs a fetcher over one or
all characters, with a corp variant that resolves each character's corp id.
account._run now reuses it.

27 tools total, 70 tests, coverage 91%. Closes #18 and #19; covers most of #20.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 19:28:21 +02:00
LatteandClaude Opus 4.8 61837d4783 Multi-character support across accounts
CI / lint (pull_request) Successful in 49s
CI / test (pull_request) Successful in 56s
CI / lint (push) Successful in 50s
CI / publish (pull_request) Has been skipped
CI / test (push) Successful in 55s
CI / publish (push) Successful in 50s
Rework the token store to hold many characters keyed by character_id,
migrating the previous single-character file transparently. `familiar login`
now adds a character; `familiar status` lists all; `familiar logout [name|id]`
removes one or all.

Every account tool gains an optional `character` (name or id): omitted means
all logged-in characters, given means just that one. Results are uniform
{"characters": [...]}. get_auth refreshes per character.

58 tests, coverage 89%. Closes #9

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 18:47:34 +02:00
LatteandClaude Opus 4.8 eb6440db40 Phase 2: EVE SSO auth + read-only account tools
CI / lint (pull_request) Successful in 51s
CI / lint (push) Successful in 50s
CI / test (pull_request) Successful in 57s
CI / publish (pull_request) Has been skipped
CI / test (push) Successful in 57s
CI / publish (push) Successful in 50s
Add PKCE OAuth2 login against EVE SSO with an encrypted, auto-refreshing
token store, driven by `familiar login` / `status` / `logout` CLI commands.
The MCP server gains authenticated account tools:

- account_status, get_wallet, get_skills, get_skill_queue
- get_location, get_clones, get_assets (paginated)

ESI client extended with Bearer auth and X-Pages pagination. 51 tests
(auth + account mocked), coverage 88%. Client id/callback/scopes are
env-overridable; refresh token Fernet-encrypted on disk.

Closes #7

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 18:32:47 +02:00
LatteandClaude Opus 4.8 4223141cf7 Phase 1: public market + universe lookups via ESI
CI / test (pull_request) Successful in 56s
CI / publish (pull_request) Has been skipped
CI / lint (push) Successful in 52s
CI / test (push) Successful in 56s
CI / publish (push) Failing after 34s
CI / lint (pull_request) Successful in 52s
Add a thin async ESI client (httpx, descriptive User-Agent, uniform errors,
mockable transport) plus name<->id resolution. New read-only tools:

- universe: resolve_names, get_item, get_system, get_station, get_region, get_route
- market:   list_hubs, get_market_price, get_market_orders, compare_hubs

Trade-hub IDs (Jita/Amarr/Dodixie/Rens/Hek) are hardcoded constants. Market
aggregation (best buy/sell, spread, order book) lives in pure helpers. 30 unit
tests with mocked ESI; coverage 99%. SDE bulk-load deferred to a later phase.

Closes #2

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 17:49:40 +02:00
LatteandClaude Opus 4.8 ef27cd85f6 Phase 0: FastMCP scaffold with ping tool
Set up the familiar package (src layout, uv/hatchling) with a FastMCP
server exposing a read-only ping health tool. Add pytest smoke tests with
80% coverage gate. Flesh out the README with the project vision and roadmap.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 17:34:51 +02:00