Skip to content

Add self-hosted CoPE model support to Zentropi integration - #806

Draft
reitblatt wants to merge 7 commits into
roostorg:mainfrom
reitblatt:self-hosted-cope-zentropi
Draft

Add self-hosted CoPE model support to Zentropi integration#806
reitblatt wants to merge 7 commits into
roostorg:mainfrom
reitblatt:self-hosted-cope-zentropi

Conversation

@reitblatt

@reitblatt reitblatt commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Addresses #751

Summary

  • Adds support for self-hosted CoPE/vLLM inference within the existing Zentropi integration
  • New selfHosted config fields (format, baseUrl, model, optional apiKey, prompt templates) stored in a new self_hosted_* column set on the zentropi_configs table
  • Routes hosted vs. self-hosted at runtime: hosted calls the Zentropi API with a labeler_version_id; self-hosted calls an OpenAI-compatible completions or chat endpoint with configurable prompt templates
  • Rule builder now shows a free-text "Policy Criteria" textarea (instead of a subcategory dropdown) when Zentropi is in self-hosted mode; hosted mode continues to surface configured labeler versions as a dropdown

Test plan

  • Configure Zentropi integration in hosted mode (API key + labeler versions) — verify labeler version dropdown appears in rule builder and scoring works
  • Configure Zentropi integration in self-hosted mode (vLLM/OpenAI-compatible endpoint) — verify "Policy Criteria" textarea appears in rule builder
  • Enter policy criteria text, save rule, run against items — verify score is returned from the self-hosted endpoint
  • Verify cope format (completions endpoint) and openai_chat format (chat/completions endpoint) both work
  • Verify disabled state when neither API key nor self-hosted config is present
  • Run server unit tests: cd server && npm test

🤖 Generated with Claude Code

reitblatt and others added 2 commits June 17, 2026 11:00
…oostorg#751)

Adds the ability to run a vLLM-served CoPE model as an alternative to
the Zentropi hosted API, without adding a new signal type. Users choose
between hosted mode (API key + labeler_version_id) and self-hosted mode
(base URL, model name, and format) in the Zentropi integration settings.

Two self-hosted formats are supported:
- cope: vLLM /v1/completions with the CoPE fixed-prompt template
- openai_chat: configurable chat completions with {criteria}/{content} templates

Score extraction uses logprobs in both cases, producing 0–1 output
matching the Zentropi hosted scale. Shared openaiCompatibleUtils module
is factored for reuse in future self-hosted integrations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d rules (roostorg#751)

When Zentropi is configured in self-hosted mode, the rule builder now shows
a free-text textarea to enter policy criteria, rather than the standard
subcategory gallery. Hosted mode continues to show labeler versions as a
dropdown. Also removes temporary debug logging from zentropiUtils.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d8655b98-1a18-4d05-ad1f-b516aa8c8082

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

reitblatt and others added 5 commits June 18, 2026 11:48
…storg#751)

Policies created via the tiptap editor store empty state as "<p></p>"
rather than null. This passes the policyText truthiness filter but
strips to an empty string, which would produce meaningless classifier
criteria. Fix in two places:

- resolvePolicyCriteria now throws a SignalPermanentError if the
  HTML-stripped criteria text is empty, rather than silently passing ""
  to the self-hosted model endpoint.
- eligibleSubcategories filter now also strips HTML before filtering, so
  policies with HTML-only text never appear in the policy picker and
  can't be selected as signal criteria.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…criteria (roostorg#751)

Self-hosted Zentropi rules can now use an existing org policy object as
classifier criteria instead of free text:

- Signal subcategory gallery shows a Radio toggle between "Existing
  Policy" (Select dropdown) and "Custom Text" (textarea) when the org
  has at least one policy with usable text.
- Selecting a policy stores subcategory as "policy:<id>"; the server
  resolves this to the policy's stripped policyText at signal run time.
- Condition display shows the policy name (not the raw ID) when a
  policy reference is stored.
- When a policy is chosen as criteria and no policies are assigned to
  the rule yet, policyIds is auto-populated with that policy's ID.
- ZentropiLabelerSignal now accepts a getPolicyText callback (injected
  via instantiateBuiltInSignals) that fetches policyText from
  ModerationConfigService at run time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix email validation in invite user form

The invite form accepted comma-separated email lists and didn't surface
why the submit button was disabled. This fixes three things:

- Thread the `type` prop through CoopInput to the underlying <input>
- Validate email format client-side (rejecting commas, which were the
  original bug vector) and mark the field red when invalid
- Show a contextual tooltip on the disabled submit button explaining
  what's missing (no email, invalid email, or no role selected)

Fixes roostorg#411

* Destructure value for consistency, add aria-invalid for a11y
* fix: don't hide empty threads

* code review fixes

* code review fixes

---------

Co-authored-by: Juan Mrad <juansmrad@gmail.com>
…pe casts (roostorg#666)

* refactor: migrate CoreSignal to GQLSignal, remove redundant client type casts

* fix: address Copilot and CodeRabbit review comments

* fix: address Copilot review pass

* code review fixes

* fix code review. add missing test

---------

Co-authored-by: Juan Mrad <juansmrad@gmail.com>
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.

3 participants