Skip to content

feat(events): add action/entity filters, enforce type/severity enums, drop table display hints#15

Merged
Seraf merged 7 commits into
masterfrom
feat/event-filters-and-display-cleanup
Jun 5, 2026
Merged

feat(events): add action/entity filters, enforce type/severity enums, drop table display hints#15
Seraf merged 7 commits into
masterfrom
feat/event-filters-and-display-cleanup

Conversation

@Seraf

@Seraf Seraf commented Jun 5, 2026

Copy link
Copy Markdown
Member

Summary

Three related improvements to the Cycloid event tools, surfaced while debugging the Ask-Cycloid companion.

  • Event filteringCYCLOID_EVENT_LIST and CYCLOID_PROJECT_EVENTS now accept free-form action (create, configure, pause, …) and entity (component, build, ci_build, …) filters, applied client-side against each event's tags since the CLI only filters by type/severity/begin/end. Fixes the companion repeatedly passing action names where they don't belong.
  • Type/severity guardtype and severity are now constrained via Literal enums to the values cy event list accepts (Cycloid/AWS/Monitoring/Custom and info/warn/err/crit), so invalid values are rejected at the tool schema instead of triggering an API 422.
  • Display hints removed — dropped the _display_hints/build_display_hints mechanism and all "DISPLAY GUIDANCE: … markdown table" text from every tool (and deleted src/display_hints.py). Tools return clean JSON and let the client choose how to render it; formatting is a presentation concern, not a data-layer one, and the column hints were producing unreadable wide tables in a narrow chat.

Testing

  • make test — 102 passing
  • make type-check — pyright strict clean
  • make lint — flake8 clean

🤖 Generated with Claude Code

Seraf and others added 7 commits May 26, 2026 09:18
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds two new MCP tools to support the cyclobot chat's "who worked on this
project" use case and member-chip URL construction.

CYCLOID_PROJECT_EVENTS(project) walks project -> envs -> components in
parallel via asyncio.gather, fetches org events once, then filters by the
"project" tag. Surfaces a deduplicated `actors` list extracted from
tags[key=user] so the LLM does not have to parse tags manually. Bounded
by a 50-component hard cap (configurable via
CYCLOID_PROJECT_EVENTS_MAX_COMPONENTS) to keep wall time predictable.

CYCLOID_MEMBER_LIST wraps `cy members list` so the LLM can cross-reference
a username (the only actor identifier present in events) to the numeric
member `id` required by the `/organizations/<org>/members/<id>` route.

CYCLOID_EVENT_LIST is widened to return the full event payload including
the tags array (previously trimmed). The display hints now include the
tags column so the LLM can show actor identity in tables.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Live activity-feed events for cycloid-saas were not surfacing in
CYCLOID_PROJECT_EVENTS even though the same events appeared in the
project's Activity tab. Root cause: the filter looked for
`tags[key=project]`, but Cycloid platform events (ci_build, configure,
pause/unpause, …) only carry `tags[key=project_canonical]` — the
legacy `project` tag is present on older Custom-type events but not on
the bulk of activity.

Switch the filter to a `_event_belongs_to_project` helper that matches
either `project_canonical` (the canonical key) or `project` (the legacy
fallback). The activity tab itself uses `project_canonical[in]=` against
the HTTP API, so this aligns the MCP client-side filter with what the
UI already does.

Actor extraction has the same dual-shape problem: Cycloid platform
events carry `tags[key=member_id]` — the numeric id directly usable in
the `/organizations/<org>/members/<id>` URL — while Custom events carry
only `tags[key=user]` (a username that requires a CYCLOID_MEMBER_LIST
lookup). `_extract_actors` now surfaces whichever identifier the event
provides, deduplicated, so the LLM can skip the member-list round-trip
whenever an `id` is present.

Adds a regression test using the live cycloid-saas event shape
(`project_canonical` + `member_id`, no `project`/`user` tags).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds project-scoped tools wrapping `cy project` and `cy components`
CLI subcommands, exposing project listing/lookup and component
listing/lookup as MCP tools with corresponding test suites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…logs

- _get_components: pass each canonical via the --component flag (one CLI
  call per canonical). The documented `cy components get [canonical...]`
  positional form is silently ignored by the CLI (v6.10.x) and fails with
  "component is not set, use --component flag" — only --component is
  honored, and it is single-valued. (`cy project get` positional works and
  has no -c flag, so projects.py is intentionally left unchanged.)
- cli.py: surface stderr / exit code / timeout / exception detail in the
  visible log message. FastMCP's Rich handler drops the `extra` dict, so
  failures previously showed only an opaque "CLI command failed with exit
  code 1"; the reason is now in the message (API key stays env-injected,
  never in the logged command).
- get_components: log a warning with project/env/detail before raising
  ToolError, so the tool name and scope are visible without the framework
  line.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… drop table display hints

Three related improvements to the Cycloid event tools, surfaced while debugging
the Ask-Cycloid companion:

- Event filtering: CYCLOID_EVENT_LIST and CYCLOID_PROJECT_EVENTS now accept
  free-form `action` (create, configure, pause, ...) and `entity` (component,
  build, ci_build, ...) filters, applied client-side against each event's tags
  since the CLI only filters by type/severity/begin/end. Fixes the companion
  repeatedly passing action names where they don't belong.

- Type/severity guard: `type` and `severity` are now constrained via Literal
  enums to the values `cy event list` accepts (Cycloid/AWS/Monitoring/Custom and
  info/warn/err/crit), so invalid values are rejected at the tool schema instead
  of triggering an API 422.

- Display hints removed: dropped the `_display_hints`/`build_display_hints`
  mechanism and all "DISPLAY GUIDANCE: ... markdown table" text from every tool
  (and deleted src/display_hints.py). Tools return clean JSON and let the client
  choose how to render it; formatting is a presentation concern, not a data-layer
  one, and the column hints were producing unreadable wide tables in a narrow chat.

Tests updated accordingly (102 passing); pyright strict and flake8 clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Seraf
Seraf merged commit 99b1eb1 into master Jun 5, 2026
1 check passed
@Seraf
Seraf deleted the feat/event-filters-and-display-cleanup branch June 5, 2026 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant