Skip to content

Add Prompt Compressor Policy v0.1#176

Merged
renuka-fernando merged 13 commits intomainfrom
python-policies
Apr 27, 2026
Merged

Add Prompt Compressor Policy v0.1#176
renuka-fernando merged 13 commits intomainfrom
python-policies

Conversation

@renuka-fernando
Copy link
Copy Markdown
Contributor

@renuka-fernando renuka-fernando commented Apr 25, 2026

Purpose

Fix wso2/api-platform#1714
Related PR: #173

Add the prompt-compressor policy to reduce prompt size before upstream LLM calls and document how to include and configure it.

Goals

  • Compress selected prompt text in JSON request bodies.
  • Support JSONPath-based prompt targeting.
  • Support rule-based compression using ratio or target-token modes.
  • Support selective compression using <APIP-COMPRESS> tags.
  • Add policy hub documentation for docs/prompt-compressor/v0.1.

Approach

  • Added the prompt-compressor policy package under policies/prompt-compressor.
  • Added policy-definition.yaml, package metadata, requirements, and README.
  • Added policy documentation and metadata under docs/prompt-compressor/v0.1.
  • Documented the build.yaml entry:
- name: prompt-compressor
  pipPackage: github.com/wso2/gateway-controllers/policies/prompt-compressor@v0

Documentation

Added documentation:

  • docs/prompt-compressor/v0.1/docs/prompt-compressor.md
  • docs/prompt-compressor/v0.1/metadata.json

Automation tests

  • Documentation/catalog validation completed.
  • Package/runtime tests: N/A for this PR.

Security checks

  • Followed secure coding standards: yes
  • Ran FindSecurityBugs plugin and verified report: N/A
  • Confirmed no keys, passwords, tokens, usernames, or other secrets are committed: yes

Samples

Included sample policy configurations in the Prompt Compressor documentation.

Related PRs

N/A

Test environment

Local development environment.

sehan-dissanayake and others added 8 commits April 23, 2026 15:22
Introduce a new prompt-compressor policy for the WSO2 AI Gateway (version 0.1.0). Adds package files (README.md, __init__.py, policy-definition.yaml, policy.py, pyproject.toml, requirements.txt) implementing a Python executor policy that buffers request bodies, extracts a prompt via a configurable jsonPath (default $.messages[0].content), and applies configurable compression rules. Supports selective compression using <APIP-COMPRESS> tags, rule-based ratio/token modes, dynamic metadata reporting, and uses the compression-prompt dependency. Includes packaging metadata so the policy can be installed/consumed by the gateway builder.
Add Prompt Compressor v0 documentation and metadata, and adjust package layout and imports. Files added: docs/prompt-compressor/v0.1/docs/prompt-compressor.md and docs/prompt-compressor/v0.1/metadata.json; docs/README.md updated to list the new policy. policies/prompt-compressor/README.md simplified usage and updated the build.yaml pipPackage example. policy.py import updated from wso2_gateway_policy_sdk to apip_sdk_core. pyproject.toml updated to rename the package and Python package directory from prompt_compressor to prompt_compressor_v0 (including package-data mapping) to reflect the v0 packaging changes.
Introduce comprehensive unit tests for the prompt-compressor policy (policies/prompt-compressor/test_policy.py). Adds fake dependency stubs and a FakeCompressor to exercise policy behavior: mode selection, params normalization and sorting, rule selection and ratio resolution, JSONPath extraction/updating and error cases, selective tagging and nested tag handling, on_request_body transformations and metadata, non-fatal and fatal compressor errors, and compressor instance caching by rounded ratio.
Add a new "Notes" section to the prompt-compressor docs covering semantic preservation, compression efficiency caveats, and a list of protected content types (code blocks, JSON, file paths/URLs, technical identifiers, hashes/large numbers, and bracketed content).
Co-authored-by: Renuka Piyumal Fernando <renukapiyumal@gmail.com>
Co-authored-by: Renuka Piyumal Fernando <renukapiyumal@gmail.com>
Rename the request context parameter from ctx to req_ctx in policy.on_request_body and update all references (body access and guards) accordingly. Update unit tests to call on_request_body with req_ctx and adjust a long test line for readability. Simplify README to briefly describe the package as a Python policy that compresses prompt text.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 25, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1fea640d-2fdb-483a-8c93-709614b122f8

📥 Commits

Reviewing files that changed from the base of the PR and between 44d3ee9 and 9b5ef5b.

📒 Files selected for processing (3)
  • docs/prompt-compressor/v0.1/docs/prompt-compressor.md
  • policies/prompt-compressor/policy-definition.yaml
  • policies/prompt-compressor/pyproject.toml
✅ Files skipped from review due to trivial changes (1)
  • docs/prompt-compressor/v0.1/docs/prompt-compressor.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • policies/prompt-compressor/pyproject.toml
  • policies/prompt-compressor/policy-definition.yaml

📝 Walkthrough

Summary

This PR adds a new Prompt Compressor policy (v0.1) to the gateway, enabling automatic compression of selected prompt text in JSON request bodies before forwarding to upstream LLM services.

Changes Overview

Policy Implementation

  • Policy Package (policies/prompt-compressor/): A complete Python policy package with ~450 lines of implementation code
    • Core policy class (PromptCompressorPolicy) that processes request bodies and applies compression logic
    • Supports rule-based compression with ordered evaluation by token limits
    • Implements two compression modes: ratio-based (fixed retention percentage) and token-based (derived from estimated token count)
    • Handles selective compression using <APIP-COMPRESS> tags for targeting specific regions within prompts
    • Returns upstream request modifications with updated JSON bodies and dynamic metadata (compression statistics and token estimates)
    • Includes input validation and error handling for malformed JSON, missing JSONPath targets, and invalid configurations

Documentation & Metadata

  • Policy Hub Documentation (docs/prompt-compressor/v0.1/): ~270 lines of comprehensive documentation

    • Detailed functional specification covering compression modes, rule evaluation order, and selective tagging behavior
    • Integration steps and three concrete configuration examples with sample requests and expected outputs
    • Operational notes on semantic preservation and efficiency expectations
  • Policy Metadata (docs/prompt-compressor/v0.1/metadata.json): Versioned metadata file defining policy identity, version, provider (WSO2), and category (AI)

  • Package Documentation (policies/prompt-compressor/README.md): Brief package overview

Configuration & Dependencies

  • Build Configuration (pyproject.toml): Standard Python package metadata with Apache 2.0 license, Python 3.10+ requirement
  • Dependencies (requirements.txt): Single pinned dependency on compression-prompt==0.1.2 library
  • Policy Definition (policy-definition.yaml): Schema and configuration structure defining:
    • jsonPath parameter for targeting specific JSON fields (defaults to $.messages[0].content)
    • Required rules array with ordered compression rules, each specifying upper token limit, compression type, and configuration value
    • Requires a catch-all fallback rule with upperTokenLimit: -1

Testing & Quality

  • Comprehensive Test Suite (test_policy.py): ~395 lines covering:
    • Parameter normalization and validation
    • Rule selection and ratio resolution logic
    • JSONPath extraction and in-place JSON updates
    • End-to-end policy behavior with various input scenarios
    • Selective tag-based compression with nested tag handling
    • Compressor instance caching and reuse optimization
    • Error cases and fallback behavior

Documentation Updates

  • Catalog Entry (docs/README.md): Added new policy row to the "Available Policies" table with link to v0.1 documentation

Key Features

  • JSONPath-based targeting: Compress specific JSON fields by path expression
  • Rule-driven compression: Multiple configurable rules evaluated in token-limit order
  • Selective compression: Optional <APIP-COMPRESS> tags limit compression to tagged regions
  • Dynamic metadata: Returns compression statistics and token estimates as request metadata
  • Graceful degradation: Skips modification on parse errors, missing targets, or compression failures

Walkthrough

This change introduces a new Prompt Compressor policy (v0.1.0) to the gateway system. The policy reduces JSON prompt size by extracting a target string via JSONPath, applying compression rules based on configured token limits and compression modes (ratio or token type), and optionally handling selective compression regions marked with <APIP-COMPRESS> tags. The implementation includes a complete policy definition, Python implementation with caching, comprehensive unit tests, build configuration, and documentation. The policy returns modified request bodies with dynamic metadata containing compression statistics or skips modification for invalid/unsafe requests.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Gateway as "Gateway\nPromptCompressorPolicy"
    participant Compressor as "Compressor\n(cache)"
    participant Upstream as "Upstream LLM"

    Client->>Gateway: HTTP request with JSON body
    Gateway->>Gateway: Buffer body, parse JSON
    Gateway->>Gateway: Extract target string via jsonPath
    alt selective tags present
        Gateway->>Gateway: Identify <APIP-COMPRESS> regions
        Gateway->>Compressor: Request compression per region (resolved ratio)
    else no tags
        Gateway->>Compressor: Request compression for whole target (resolved ratio)
    end
    Compressor-->>Gateway: Compressed text (or error/no-op)
    Gateway->>Gateway: Update JSON value, remove tags, compact serialize
    Gateway->>Upstream: Forward modified request with dynamic_metadata
    Upstream-->>Client: Upstream response (unchanged by policy)
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add Prompt Compressor Policy v0.1' clearly and concisely summarizes the main change, specifying the new policy being added.
Description check ✅ Passed The description covers primary sections including Purpose (with issue link), Goals, Approach, Documentation, Automation tests, Security checks, and Test environment, providing sufficient context.
Linked Issues check ✅ Passed The PR successfully implements the coding requirements from issue #1714: a complete Python policy implementation with documentation, configuration, testing, and packaging for GitHub.
Out of Scope Changes check ✅ Passed All changes are directly related to the Prompt Compressor Policy implementation: policy code, configuration, documentation, tests, and package metadata. No unrelated changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch python-policies

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.

@renuka-fernando renuka-fernando changed the title Add Prompt Compressor Policy Add Prompt Compressor Policy v0.1 Apr 25, 2026
@renuka-fernando
Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 25, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (13)
docs/prompt-compressor/v0.1/docs/prompt-compressor.md (2)

184-189: Clarify the behavior when value exceeds the estimated token count in token mode.

For the fallback rule { upperTokenLimit: -1, type: token, value: 1200 }, prompts whose estimated tokens are at or below 1200 result in the rule being skipped (per the implementation, resolve_ratio returns None when target_tokens >= estimated_tokens). The current wording suggests the rule always "targets approximately 1200 retained tokens." A short note that the rule is a no-op when the prompt is already at/under the target would help readers reason about edge cases.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/prompt-compressor/v0.1/docs/prompt-compressor.md` around lines 184 -
189, Clarify that in token mode (e.g., the fallback rule with upperTokenLimit:
-1, type: token, value: 1200) the rule is a no-op when the prompt's estimated
token count is already <= value: the implementation's resolve_ratio function
returns None if target_tokens >= estimated_tokens, so add a short note stating
the rule only applies when estimated_tokens > value and is skipped otherwise.

50-58: Document behavior for malformed selective-compression tags.

The "Selective Compression Tags" section explains the happy path but does not document what happens when tags are unmatched (e.g., a stray </APIP-COMPRESS> or an unclosed <APIP-COMPRESS>). Based on the implementation snippet shared, the policy tolerates these cases (an unclosed open tag still compresses the trailing region; a stray close tag is dropped). Please document the expected handling so users can rely on it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/prompt-compressor/v0.1/docs/prompt-compressor.md` around lines 50 - 58,
Update the "Selective Compression Tags" section to document handling of
malformed tag pairs for `<APIP-COMPRESS>` and `</APIP-COMPRESS>`: state that an
unmatched opening tag compresses until end-of-string (i.e., an unclosed
`<APIP-COMPRESS>` will compress the trailing region) and that stray closing tags
(`</APIP-COMPRESS>`) are ignored/dropped; also clarify that tags are removed
from the final forwarded text and that behavior applies when using
selective-region compression in the policy.
policies/prompt-compressor/__init__.py (1)

1-3: LGTM.

__version__ here matches pyproject.toml (0.1.0). Consider sourcing it from package metadata (e.g., importlib.metadata.version("prompt-compressor-v0")) in a future iteration to avoid drift between the two files.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@policies/prompt-compressor/__init__.py` around lines 1 - 3, Current
__version__ in policies/prompt-compressor/__init__.py is hardcoded as "0.1.0"
which can drift from pyproject.toml; replace the hardcoded __version__ with a
runtime lookup using importlib.metadata.version("prompt-compressor-v0") (or
importlib_metadata for older Python) and set __version__ to that value, adding a
fallback (e.g., default string or empty) and handling PackageNotFoundError so
imports won’t fail when metadata is unavailable; update the module-level symbol
__version__ and ensure any import names remain unchanged.
policies/prompt-compressor/README.md (1)

1-3: Consider expanding the package README.

A single sentence is sufficient as a placeholder, but a brief section on configuration entry points and a link to docs/prompt-compressor/v0.1/docs/prompt-compressor.md would help developers landing here from PyPI or pip show.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@policies/prompt-compressor/README.md` around lines 1 - 3, Update the README
for the prompt-compressor package to include a one-sentence placeholder summary
plus a short "Configuration" section that lists the package entry points and
where to configure behavior (e.g., environment variables, config files, or
middleware hooks used by the prompt-compressor package) and add a direct link to
docs/prompt-compressor/v0.1/docs/prompt-compressor.md so external devs (pip/
PyPI consumers) can quickly find usage and configuration details; ensure the
README still includes the original package description and the linked docs path.
policies/prompt-compressor/policy-definition.yaml (3)

39-56: Document or constrain value semantics per type.

value is declared as number, so floats are accepted in both modes. In token mode the implementation casts to int, which silently truncates fractional values (e.g., value: 800.9800). Either tighten the description to state the truncation, or split into per-mode validation (e.g., exclusiveMinimum: 0, plus a note that token mode expects an integer-valued number). At minimum, add exclusiveMinimum: 0 so non-positive values are rejected during validation rather than silently ignored at runtime.

♻️ Suggested change
           value:
             type: number
+            exclusiveMinimum: 0
             description: |
               Rule value. For "ratio", use a retained-size ratio such as 0.8.
-              For "token", use the target retained token estimate.
+              For "token", use the target retained token estimate. Fractional
+              values in "token" mode are truncated to an integer.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@policies/prompt-compressor/policy-definition.yaml` around lines 39 - 56, The
schema currently allows any number for the "value" property but the
implementation truncates fractional values in token mode; update the
policy-definition.yaml to validate and document per-type semantics: add
"exclusiveMinimum: 0" to "value" to reject non-positive numbers, and enforce
integer-only for token mode (e.g., use an if:
{properties:{type:{const:"token"}}} then: {properties:{value:{multipleOf:1}},
required:["value"]}) or alternately state in the "value" description that token
mode truncates fractions; reference the "type" enum (ratio|token), the "value"
field, and required list (upperTokenLimit/type/value) when making the change.

34-38: Consider adding a minimum: -1 constraint on upperTokenLimit.

The schema currently allows any integer (e.g., -5, -100), which the implementation silently treats as invalid. Adding minimum: -1 would surface configuration errors at validation time rather than at runtime.

♻️ Suggested change
           upperTokenLimit:
             type: integer
+            minimum: -1
             description: |
               Inclusive upper bound for the estimated token count. Use -1 as the
               fallback rule for all remaining cases.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@policies/prompt-compressor/policy-definition.yaml` around lines 34 - 38, The
schema for upperTokenLimit currently allows any integer and should enforce
minimum: -1 to prevent invalid negative values; update the
policy-definition.yaml schema for the upperTokenLimit property by adding
"minimum: -1" under upperTokenLimit (keeping the existing type and description)
so invalid values like -5 fail validation at config load rather than at runtime.

22-32: Consider documenting the "exactly one fallback" expectation.

The description states upperTokenLimit: -1 is the catch-all, but the schema does not prevent multiple rules from using -1 (only the first matching one wins after sorting). A short note in the rules description that defining more than one fallback is not recommended would help avoid configuration mistakes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@policies/prompt-compressor/policy-definition.yaml` around lines 22 - 32, The
rules array allows multiple entries with upperTokenLimit: -1 but the description
only calls it a catch-all; update the rules description to clearly state that
exactly one fallback rule (upperTokenLimit: -1) should be defined and that
defining more than one is not recommended to avoid ambiguous behavior, and
optionally add a schema-level validation note (or a custom validation rule) to
enforce or warn about multiple -1 entries; reference the rules array, its items
object and the upperTokenLimit field when making the change.
policies/prompt-compressor/pyproject.toml (1)

11-11: License classifier is redundant under PEP 639.

With setuptools>=77, the combination of license = { text = "Apache-2.0" } and the "License :: OSI Approved :: Apache Software License" classifier (line 19) is deprecated. Consider removing the classifier to align with modern practices and avoid future warnings, or simplify to license = "Apache-2.0" (string form) and drop the classifier entirely.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@policies/prompt-compressor/pyproject.toml` at line 11, The license is
declared with the table form license = { text = "Apache-2.0" } while also
including the classifier "License :: OSI Approved :: Apache Software License",
which is redundant under modern setuptools; fix by either removing the
classifier entry and keeping license = { text = "Apache-2.0" } or simplify to
license = "Apache-2.0" (string form) and drop the classifier "License :: OSI
Approved :: Apache Software License" so only the canonical license declaration
remains.
policies/prompt-compressor/requirements.txt (1)

1-1: Confirm the pinned compression-prompt==0.1.2 package source.

The version is available on PyPI with no known security advisories. The package is sourced from GitHub (https://github.com/hivellm/compression-prompt) and requires Python >=3.8. Note that this dependency is pinned in both pyproject.toml and requirements.txt in the same directory. Consider consolidating to a single source of truth if pyproject.toml is the authoritative definition for the built wheel.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@policies/prompt-compressor/requirements.txt` at line 1, Verify and document
the source and compatibility of the pinned dependency compression-prompt==0.1.2
(confirm it comes from https://github.com/hivellm/compression-prompt and
supports Python >=3.8), then consolidate dependency declarations so there is a
single authoritative source of truth: either keep the pin in pyproject.toml
(recommended for building wheels) and remove it from requirements.txt, or vice
versa; update the remaining declaration to include the source/URL and a comment
noting the Python requirement.
policies/prompt-compressor/policy.py (3)

220-222: Bare except Exception is intentional defensive guard.

Acknowledged via the # pragma: no cover comment; this prevents an upstream library bug from breaking the request path. No change needed, but consider logging at error level (rather than warning) and including the exception type for easier post-mortem in production logs.

♻️ Optional tweak
-        except Exception as exc:  # pragma: no cover - defensive guard for library/runtime issues
-            LOGGER.warning("PromptCompressor: unexpected compression failure: %s", exc)
+        except Exception as exc:  # pragma: no cover - defensive guard for library/runtime issues
+            LOGGER.exception("PromptCompressor: unexpected compression failure (%s)", type(exc).__name__)
             return text, False
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@policies/prompt-compressor/policy.py` around lines 220 - 222, Change the log
level and enrich the message in the exception handler that currently does
"LOGGER.warning(...)" (the except block in the PromptCompressor compression flow
— look for the LOGGER usage in the compress/attempt_compress method). Replace
the warning with LOGGER.error and include the exception's type/name alongside
the message and exception instance (e.g., include type(exc).__name__ plus exc)
so production logs show the exception class and details for post-mortem while
keeping the existing fallback return of (text, False).

25-25: JSONPath support is intentionally minimal; document limitations or adopt a library.

The custom resolver only handles $-rooted, dot-segmented paths with optional name[index] array access. Common JSONPath features (bracketed string keys like ['messages'], multi-index [0][1], recursive descent .., filter expressions, wildcards, escaped dots in keys) are silently rejected. For v0.1 this may be acceptable, but consider either:

  • documenting the supported subset prominently in the README/policy docs, or
  • delegating to a maintained library (e.g., jsonpath-ng) to reduce custom parsing surface and make user-supplied paths behave predictably.

Also applies to: 412-453

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@policies/prompt-compressor/policy.py` at line 25, The custom JSONPath
resolver in policy.py (the `_ARRAY_INDEX_RE` regex and the resolver logic around
the same module that handles `$`-rooted, dot-segmented paths) is overly limited;
either explicitly document the supported subset in the policy/README (call out
unsupported features like bracketed string keys, recursive `..`, filters,
wildcards, escaped dots, multi-indexing) or replace the custom parsing with a
maintained library (e.g., use `jsonpath-ng` to evaluate user-supplied paths),
updating the resolver entrypoint to call the library and adjusting tests and
error messages accordingly so unsupported inputs are handled predictably.

379-409: Minor: redundant regex match in set_value_at_jsonpath.

Line 389 calls _ARRAY_INDEX_RE.match(final_component), then line 391 calls parse_array_component(final_component) which re-runs the same regex. Same redundancy exists in get_path_component (lines 424–426). Negligible cost, but trivially deduplicable by inlining the match result.

♻️ Proposed refactor
-    final_component = components[-1]
-    match = _ARRAY_INDEX_RE.match(final_component)
-    if match:
-        array_name, index = parse_array_component(final_component)
+    final_component = components[-1]
+    match = _ARRAY_INDEX_RE.match(final_component)
+    if match:
+        array_name = match.group(1)
+        index = int(match.group(2))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@policies/prompt-compressor/policy.py` around lines 379 - 409, The code
redundantly calls _ARRAY_INDEX_RE.match(final_component) and then calls
parse_array_component(final_component) which repeats the regex; update
set_value_at_jsonpath (and similarly get_path_component) to reuse the initial
match result: store match = _ARRAY_INDEX_RE.match(final_component), and if match
is truthy extract the array name and index from match.groups() (or call a new
parse_array_component_from_match(match) helper) instead of re-invoking
parse_array_component(final_component); adjust error handling to use the reused
match-derived values so the regex is executed only once per component.
policies/prompt-compressor/test_policy.py (1)

62-68: Use ClassVar annotation for the shared instance registry.

Ruff (RUF012) flags the mutable list as a class attribute without ClassVar typing. Since instances is intentionally shared across instances for test inspection, annotate it explicitly to silence the lint and document intent.

♻️ Proposed refactor
+from typing import ClassVar
@@
 class FakeCompressor:
-    instances: list["FakeCompressor"] = []
+    instances: ClassVar[list["FakeCompressor"]] = []
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@policies/prompt-compressor/test_policy.py` around lines 62 - 68, The
class-level mutable registry FakeCompressor.instances should be annotated as a
ClassVar to satisfy RUF012 and document intent; import ClassVar from typing and
change the annotation to ClassVar[list["FakeCompressor"]] for the instances
attribute in the FakeCompressor class so the shared list is explicitly marked as
a class variable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/prompt-compressor/v0.1/docs/prompt-compressor.md`:
- Around line 263-265: The "Compression Efficiency" note is ambiguous; update
the text for clarity by stating that achieved compression ratios are often less
aggressive than the configured/expected target because protected content and
conservative defaults limit how much can be removed — e.g., replace the existing
sentence about a "considerable gap" with a clear statement that the policy
typically yields less reduction than the target (not that the compressed prompt
becomes larger than the original) and mention that protected regions and
retention ratios are the primary constraints.

In `@policies/prompt-compressor/policy.py`:
- Around line 9-16: The imports of Compressor, CompressorConfig and the
exceptions CompressionError, InputTooShortError, NegativeGainError rely on the
non-existent PyPI package declared as compression-prompt==0.1.2; fix by updating
the dependency to the correct package name/version or switching to a supported
alternative and adjust imports accordingly (e.g., replace imports from
compression_prompt with the real package or local module providing
Compressor/CompressorConfig and the three exception classes), and ensure
pyproject.toml reflects that valid package source (or add the private index
configuration) so the module can import Compressor, CompressorConfig,
CompressionError, InputTooShortError, and NegativeGainError successfully.

In `@policies/prompt-compressor/pyproject.toml`:
- Around line 28-36: The pyproject config currently uses package auto-discovery
with [tool.setuptools] packages = ["prompt_compressor_v0"] and
[tool.setuptools.package-dir] prompt_compressor_v0 = "." which causes
test_policy.py to be packaged; fix by preventing test files from being included:
either add a [tool.setuptools.packages.find] section with skip = ['*test*'] to
exclude test modules, or replace the auto-discovery with an explicit py-modules
= ["policy"] entry so only the intended module is packaged, or move
test_policy.py out of the package root into a top-level tests/ directory; update
the prompt_compressor_v0/package-dir or packages settings accordingly so tests
are not shipped.

---

Nitpick comments:
In `@docs/prompt-compressor/v0.1/docs/prompt-compressor.md`:
- Around line 184-189: Clarify that in token mode (e.g., the fallback rule with
upperTokenLimit: -1, type: token, value: 1200) the rule is a no-op when the
prompt's estimated token count is already <= value: the implementation's
resolve_ratio function returns None if target_tokens >= estimated_tokens, so add
a short note stating the rule only applies when estimated_tokens > value and is
skipped otherwise.
- Around line 50-58: Update the "Selective Compression Tags" section to document
handling of malformed tag pairs for `<APIP-COMPRESS>` and `</APIP-COMPRESS>`:
state that an unmatched opening tag compresses until end-of-string (i.e., an
unclosed `<APIP-COMPRESS>` will compress the trailing region) and that stray
closing tags (`</APIP-COMPRESS>`) are ignored/dropped; also clarify that tags
are removed from the final forwarded text and that behavior applies when using
selective-region compression in the policy.

In `@policies/prompt-compressor/__init__.py`:
- Around line 1-3: Current __version__ in policies/prompt-compressor/__init__.py
is hardcoded as "0.1.0" which can drift from pyproject.toml; replace the
hardcoded __version__ with a runtime lookup using
importlib.metadata.version("prompt-compressor-v0") (or importlib_metadata for
older Python) and set __version__ to that value, adding a fallback (e.g.,
default string or empty) and handling PackageNotFoundError so imports won’t fail
when metadata is unavailable; update the module-level symbol __version__ and
ensure any import names remain unchanged.

In `@policies/prompt-compressor/policy-definition.yaml`:
- Around line 39-56: The schema currently allows any number for the "value"
property but the implementation truncates fractional values in token mode;
update the policy-definition.yaml to validate and document per-type semantics:
add "exclusiveMinimum: 0" to "value" to reject non-positive numbers, and enforce
integer-only for token mode (e.g., use an if:
{properties:{type:{const:"token"}}} then: {properties:{value:{multipleOf:1}},
required:["value"]}) or alternately state in the "value" description that token
mode truncates fractions; reference the "type" enum (ratio|token), the "value"
field, and required list (upperTokenLimit/type/value) when making the change.
- Around line 34-38: The schema for upperTokenLimit currently allows any integer
and should enforce minimum: -1 to prevent invalid negative values; update the
policy-definition.yaml schema for the upperTokenLimit property by adding
"minimum: -1" under upperTokenLimit (keeping the existing type and description)
so invalid values like -5 fail validation at config load rather than at runtime.
- Around line 22-32: The rules array allows multiple entries with
upperTokenLimit: -1 but the description only calls it a catch-all; update the
rules description to clearly state that exactly one fallback rule
(upperTokenLimit: -1) should be defined and that defining more than one is not
recommended to avoid ambiguous behavior, and optionally add a schema-level
validation note (or a custom validation rule) to enforce or warn about multiple
-1 entries; reference the rules array, its items object and the upperTokenLimit
field when making the change.

In `@policies/prompt-compressor/policy.py`:
- Around line 220-222: Change the log level and enrich the message in the
exception handler that currently does "LOGGER.warning(...)" (the except block in
the PromptCompressor compression flow — look for the LOGGER usage in the
compress/attempt_compress method). Replace the warning with LOGGER.error and
include the exception's type/name alongside the message and exception instance
(e.g., include type(exc).__name__ plus exc) so production logs show the
exception class and details for post-mortem while keeping the existing fallback
return of (text, False).
- Line 25: The custom JSONPath resolver in policy.py (the `_ARRAY_INDEX_RE`
regex and the resolver logic around the same module that handles `$`-rooted,
dot-segmented paths) is overly limited; either explicitly document the supported
subset in the policy/README (call out unsupported features like bracketed string
keys, recursive `..`, filters, wildcards, escaped dots, multi-indexing) or
replace the custom parsing with a maintained library (e.g., use `jsonpath-ng` to
evaluate user-supplied paths), updating the resolver entrypoint to call the
library and adjusting tests and error messages accordingly so unsupported inputs
are handled predictably.
- Around line 379-409: The code redundantly calls
_ARRAY_INDEX_RE.match(final_component) and then calls
parse_array_component(final_component) which repeats the regex; update
set_value_at_jsonpath (and similarly get_path_component) to reuse the initial
match result: store match = _ARRAY_INDEX_RE.match(final_component), and if match
is truthy extract the array name and index from match.groups() (or call a new
parse_array_component_from_match(match) helper) instead of re-invoking
parse_array_component(final_component); adjust error handling to use the reused
match-derived values so the regex is executed only once per component.

In `@policies/prompt-compressor/pyproject.toml`:
- Line 11: The license is declared with the table form license = { text =
"Apache-2.0" } while also including the classifier "License :: OSI Approved ::
Apache Software License", which is redundant under modern setuptools; fix by
either removing the classifier entry and keeping license = { text = "Apache-2.0"
} or simplify to license = "Apache-2.0" (string form) and drop the classifier
"License :: OSI Approved :: Apache Software License" so only the canonical
license declaration remains.

In `@policies/prompt-compressor/README.md`:
- Around line 1-3: Update the README for the prompt-compressor package to
include a one-sentence placeholder summary plus a short "Configuration" section
that lists the package entry points and where to configure behavior (e.g.,
environment variables, config files, or middleware hooks used by the
prompt-compressor package) and add a direct link to
docs/prompt-compressor/v0.1/docs/prompt-compressor.md so external devs (pip/
PyPI consumers) can quickly find usage and configuration details; ensure the
README still includes the original package description and the linked docs path.

In `@policies/prompt-compressor/requirements.txt`:
- Line 1: Verify and document the source and compatibility of the pinned
dependency compression-prompt==0.1.2 (confirm it comes from
https://github.com/hivellm/compression-prompt and supports Python >=3.8), then
consolidate dependency declarations so there is a single authoritative source of
truth: either keep the pin in pyproject.toml (recommended for building wheels)
and remove it from requirements.txt, or vice versa; update the remaining
declaration to include the source/URL and a comment noting the Python
requirement.

In `@policies/prompt-compressor/test_policy.py`:
- Around line 62-68: The class-level mutable registry FakeCompressor.instances
should be annotated as a ClassVar to satisfy RUF012 and document intent; import
ClassVar from typing and change the annotation to
ClassVar[list["FakeCompressor"]] for the instances attribute in the
FakeCompressor class so the shared list is explicitly marked as a class
variable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 513a180b-0e0b-435b-9175-e18c48c7d2fd

📥 Commits

Reviewing files that changed from the base of the PR and between 17fbd20 and bb2a583.

📒 Files selected for processing (10)
  • docs/README.md
  • docs/prompt-compressor/v0.1/docs/prompt-compressor.md
  • docs/prompt-compressor/v0.1/metadata.json
  • policies/prompt-compressor/README.md
  • policies/prompt-compressor/__init__.py
  • policies/prompt-compressor/policy-definition.yaml
  • policies/prompt-compressor/policy.py
  • policies/prompt-compressor/pyproject.toml
  • policies/prompt-compressor/requirements.txt
  • policies/prompt-compressor/test_policy.py

Comment thread docs/prompt-compressor/v0.1/docs/prompt-compressor.md Outdated
Comment thread policies/prompt-compressor/policy.py
Comment thread policies/prompt-compressor/pyproject.toml Outdated
renuka-fernando and others added 3 commits April 26, 2026 08:06
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@renuka-fernando
Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 26, 2026

✅ Actions performed

Full review triggered.

sehan-dissanayake and others added 2 commits April 27, 2026 14:58
Document and enforce that the `rules` array must include at least one fallback rule with `upperTokenLimit: -1`. The docs were updated to clarify the fallback requirement and rule evaluation order, and the policy schema (policy-definition.yaml) now uses `contains`/`const`/`minContains` to validate presence of a catch-all rule.
Require fallback rule for prompt-compressor
@renuka-fernando renuka-fernando self-assigned this Apr 27, 2026
@renuka-fernando renuka-fernando merged commit fb6d43c into main Apr 27, 2026
3 of 4 checks passed
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.

[Task]: Prompt Compression Python policy

3 participants