Skip to content

Add topic summary metadata and actions - #84

Open
cassi-volkova wants to merge 2 commits into
masterfrom
cassi/topic-summaries-api
Open

Add topic summary metadata and actions#84
cassi-volkova wants to merge 2 commits into
masterfrom
cassi/topic-summaries-api

Conversation

@cassi-volkova

@cassi-volkova cassi-volkova commented Jul 31, 2026

Copy link
Copy Markdown
Member

Summary

  • persist an LLM-generated topic summary, its exact message boundary, topic-specific system prompt, and per-summary reasoning choice
  • derive summary_has_new_messages in user topic projections and keep summary writes on the server-side internal helper; no public set_summary action exists
  • run bounded topic-summary work in the existing Messenger worker only when both the global and project database flags are enabled
  • manage a global OpenAI-compatible chat-completions endpoint registry through dedicated IAM permissions, with deterministic priority, ETag updates, generation settings, capability flags, and retryable failover
  • encrypt write-only endpoint credentials with a deployment secret and exclude them from response schemas, events, topic snapshots, and logs
  • claim topics and endpoints explicitly, perform provider calls outside database transactions, and persist bounded retry/failure state
  • wait for an available vision endpoint when new image attachments require one; use text-only processing only when no enabled vision endpoint exists
  • keep image parts in user content, keep the system prompt text-only, and send reasoning effort only to endpoints that advertise support
  • document both the read-only client workflow and the administrative API

Commits

  • 6a21b416 — topic summary metadata and the reviewed server-only write contract
  • bbbe20a5 — server-side worker, endpoint registry, feature gates, capabilities, retries, and administrative API

Validation

  • pytest -q workspace/tests/unit — 518 passed
  • pytest -q workspace/tests/integration -k "not test_verified_provider_identity_replaces_account_scoped_duplicates and not test_external_projection_move_is_request_atomic_after_each_phase and not test_external_visibility_uses_the_canonical_stream_per_logical_chat" — 117 passed, 6 deselected
  • focused endpoint/worker/OpenAI-compatible/vision/failover checks — 19 passed
  • pytest -q workspace/tests/functional — 1 passed
  • mypy -p workspace — passed (87 source files)
  • ruff check . — passed

The six excluded integration cases reproduce unchanged on the current default branch and are already tracked in #30, #65, and #79.

Migration order

Migration 0129 adds the worker settings, global endpoint registry, encrypted credential envelope, explicit claims, and bounded job state; it depends on this PR's 0128 topic-summary metadata migration.

@cassi-volkova
cassi-volkova force-pushed the cassi/topic-summaries-api branch 2 times, most recently from a5afcc3 to d5f6d18 Compare July 31, 2026 12:13

@phantomii phantomii left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested:

  1. set_summary must not be a public REST action. Topic summaries are written only by the server-side agent, so remove this route and OpenAPI contract while retaining an internal helper for the agent.

  2. set_summary_prompt must be limited to stream owners and administrators. The current allowed-role set also permits moderators; remove that role and update the corresponding tests and API documentation.

@cassi-volkova
cassi-volkova force-pushed the cassi/topic-summaries-api branch from d5f6d18 to 6a21b41 Compare July 31, 2026 15:32
@cassi-volkova

Copy link
Copy Markdown
Member Author

Both review points are now reflected in the contract.

Topic-summary writes no longer have a public route or OpenAPI operation; the server-side helper remains the only write path, including boundary validation, stale-job protection, and topic.updated fan-out. Prompt changes now reject moderators and allow only stream owners and administrators, with the role tests and documentation matching that rule. I also rewrote the client example so the UI only reads summary state and consumes topic.updated, while LLM scheduling and summary writes stay server-side.

The updated commit is 6a21b416. The full local unit and filtered integration suites, focused summary/migration checks, Ruff, and mypy pass, and all 15 GitHub checks are green.

@cassi-volkova
cassi-volkova requested a review from phantomii July 31, 2026 15:36
@phantomii

Copy link
Copy Markdown
Member

Please add the following in a new commit before this PR is approved.

Implement server-side topic summarization on the existing gcl_looper Messenger worker path:

  • Add a bounded summary step that finds topics requiring refresh (summary is absent or summary_has_new_messages is true) in projects where topic summarization is enabled. It must claim/lock one topic at a time, snapshot the message boundary and effective prompt, call the selected LLM, and persist through the existing internal summary helper. Do not add a public set_summary action.
  • Add a project-level enable/disable setting. It gates summarization for every stream in that project; endpoint selection is not per-project or per-stream.
  • Add a database-backed global LLM endpoint registry and API. Only callers with a dedicated endpoint-management permission may create, update, enable/disable, or reprioritize endpoints.
  • Support multiple global endpoints with deterministic priority ordering. The worker uses the highest-priority enabled endpoint and may fail over to lower-priority enabled endpoints on a retryable provider failure.
  • Keep endpoint credentials in server-side secret storage or secret references; never return them from the API, OpenAPI schemas, logs, events, or topic snapshots.
  • Do network calls outside database transactions; keep claims, summary writes, retries, and failure state bounded and observable. Add migrations, API/policy tests, worker tests, and an end-to-end worker path test.

The shared summary remains readable by all users included in the stream; only the server-side worker writes it.

@phantomii

Copy link
Copy Markdown
Member

One protocol constraint for the new endpoint registry and worker: every configured LLM endpoint must use the OpenAI-compatible API. Store the base URL and model identifier, validate the compatible request/response contract, and invoke the chat-completions-compatible interface. Do not introduce provider-specific client branches in this first implementation.

@phantomii

Copy link
Copy Markdown
Member

Add one endpoint capability field: supports_vision (boolean). It is set and returned with the non-secret endpoint configuration. The summary worker must include image content only when the selected endpoint advertises this capability; otherwise it summarizes the textual topic content without attempting a vision request. Cover capability persistence, API validation, and worker request construction in tests.

@phantomii

Copy link
Copy Markdown
Member

Refine the vision scheduling rule:

  • If the new messages selected for a summary contain an attached image and at least one enabled supports_vision=true endpoint exists, the worker must wait/queue until a vision-capable endpoint is available. It must not fall back to a text-only endpoint merely because the preferred vision endpoint is busy.
  • Only when no enabled vision-capable endpoint exists at all may the worker summarize the same topic without images.
  • Endpoint claiming/availability must therefore be explicit and bounded, respect endpoint priority, and release the claim on success or failure. Add tests for the busy-vision wait path and the no-vision-endpoint text-only fallback.

@phantomii

Copy link
Copy Markdown
Member

Add standard generation settings to each endpoint configuration and apply them to every OpenAI-compatible request. At minimum persist and validate temperature and max_output_tokens; also include the usual supported sampling/penalty settings where applicable (for example top_p, presence_penalty, and frequency_penalty). Define explicit defaults and valid ranges, expose only non-secret settings through the endpoint-management API, and cover request serialization in tests.

@phantomii

Copy link
Copy Markdown
Member

Additional summarization requirements, consolidated:

  • Endpoint configuration represents a global, database-backed OpenAI-compatible model registry. It is managed only through a dedicated endpoint-management permission; projects only enable or disable the feature.
  • Endpoints have deterministic priority, enabled state, non-secret generation settings, and explicit capabilities such as supports_vision. Secrets must remain server-side and never appear in API responses, events, logs, or documentation examples.
  • The worker runs as a bounded gcl_looper step. It selects topics with missing or stale summaries, snapshots the topic boundary, calls the selected model, and writes only through the internal helper.
  • For a topic containing new image attachments: wait for a free enabled vision-capable endpoint whenever at least one such endpoint exists. Use text-only summarization only if no enabled vision-capable endpoint exists at all.
  • Keep images in user message content and keep the system prompt text-only.
  • Generation controls such as temperature and output-token limit belong to endpoint configuration. Reasoning is a per-summary-prompt/request choice, not an endpoint property; model-specific request mapping must be capability-aware.
  • Test permissions, priority/failover, endpoint claims, image scheduling, text-only fallback, non-secret serialization, and worker retries.

@phantomii

Copy link
Copy Markdown
Member

One additional requirement: topic summarization must also have a global enable/disable flag. The worker may process a topic only when the global flag and that project's feature setting are both enabled.

@cassi-volkova

Copy link
Copy Markdown
Member Author

The additional functionality is now implemented in the separate commit bbbe20a5.

The existing Messenger worker now claims one eligible topic and at most 100 new messages per step, snapshots the message boundary, effective prompt, and per-summary reasoning choice, then commits that claim before calling the model. Provider I/O therefore runs outside database transactions, and successful results still enter through the existing internal summary helper. Topic and endpoint leases, retry timing, attempts, and failure codes are persisted and bounded.

The control plane is database-backed: both the global flag and the current project's flag must be enabled, while endpoint selection remains global. Endpoint CRUD/reprioritization is protected by workspace.topic_summary_endpoint.manage; settings updates use the separate workspace.topic_summary_settings.manage permission. Credentials are write-only, AES-GCM encrypted with a deployment secret, excluded from response/OpenAPI schemas and events, and also hidden from object representations used by logs.

Every endpoint uses the OpenAI-compatible chat-completions contract with a base URL and model. Selection is deterministic by priority and UUID, and retryable failures release the lease and move to the next enabled endpoint. The persisted non-secret configuration includes supports_vision, a reasoning capability flag, and validated temperature, output-token, top-p, presence-penalty, and frequency-penalty settings.

The vision scheduling cases are covered end to end: a topic waits when its new image has an enabled but busy vision endpoint, without touching a free text endpoint; when no vision endpoint is enabled, the same kind of update is summarized text-only. The same test proves a real 503 failover, explicit lease release, capability-aware reasoning, images only in user content, and a text-only system prompt.

Local validation is green with 518 unit tests, 117 filtered integration tests (the same six tracked baseline exclusions), the functional suite, Ruff, and mypy. All 15 GitHub checks on bbbe20a5, including Python 3.10–3.14, coverage, and the element build, are green as well.

@phantomii phantomii left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The two earlier requests are fixed. A full lifecycle and concurrency review found three remaining correctness problems, all reproduced against the current head. The existing suite is green (518 unit tests, 7 focused integration tests, 6 migration cleanup tests, Ruff, and mypy), but it does not exercise these cases. Please address the inline findings before merge.

Comment thread migrations/0128-add-topic-summary-metadata-f3cbd4.py
Comment thread workspace/messenger_api/topic_summarization.py
Comment thread workspace/messenger_api/api/controllers.py
@cassi-volkova
cassi-volkova force-pushed the cassi/topic-summaries-api branch from bbbe20a to 066087b Compare July 31, 2026 21:25
@cassi-volkova

Copy link
Copy Markdown
Member Author

Also added the requested per-topic summary switch in 066087b. Owners and administrators can send summary_enabled through the existing summary-configuration action; false cancels pending work and prevents new claims while preserving the current summary, and true allows refreshes again. A result already in flight is discarded if the topic is disabled before completion.

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.

2 participants