context-compiler 0.7.1__tar.gz → 0.7.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {context_compiler-0.7.1 → context_compiler-0.7.2}/PKG-INFO +1 -1
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/integrations/openwebui/README.md +4 -4
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/integrations/openwebui/open_webui_pipe.py +44 -22
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/integrations/openwebui/open_webui_pipe_with_preprocessor.py +39 -20
- {context_compiler-0.7.1 → context_compiler-0.7.2}/pyproject.toml +1 -1
- {context_compiler-0.7.1 → context_compiler-0.7.2}/src/context_compiler/observability.py +1 -1
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_openwebui_pipe.py +206 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_openwebui_preprocessor_pipe.py +199 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/uv.lock +1 -1
- {context_compiler-0.7.1 → context_compiler-0.7.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/.github/pull_request_template.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/.github/workflows/ci.yml +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/.github/workflows/publish-pypi.yml +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/.github/workflows/stress-tests.yml +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/.gitignore +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/.pre-commit-config.yaml +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/AGENTS.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/CODE_OF_CONDUCT.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/CONTRIBUTING.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/LICENSE +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/README.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/SECURITY.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/01_llm_contradiction_clarify.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/02_llm_constraint_guardrail.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/03_llm_premise_guardrail.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/04_llm_tool_denylist_guardrail.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/05_llm_prompt_drift_vs_state.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/06_llm_context_compaction.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/07_llm_prompt_vs_state.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/08_llm_replacement_precondition.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/09_llm_pending_clarification.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/README.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/__init__.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/common.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/llm_client.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/demos/run_demo.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/docs/DescriptionAndMilestones.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/docs/DesignPhilosophy.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/docs/DirectiveGrammarSpec.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/docs/README.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/docs/demos-results.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/docs/llm-preprocessor.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/docs/multi-engine.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/evals/litellm_proxy_additional_findings.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/evals/litellm_proxy_behavioral_comparisons.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/evals/swe-bench/README.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/evals/swe-bench/RUBRIC.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/evals/swe-bench/manifest.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/evals/swe-bench/swe-bench.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/evals/swe-bench/tasks/django__django-12453.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/evals/swe-bench/tasks/django__django-13158.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/evals/swe-bench/tasks/django__django-13964.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/evals/swe-bench/tasks/django__django-15252.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/evals/swe-bench/tasks/matplotlib__matplotlib-23299.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/evals/swe-bench/tasks/psf__requests-1963.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/01_persistent_guardrails.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/02_configuration_and_correction.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/03_ambiguity_with_clarification.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/04_tool_governance_denylist.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/05_llm_integration_pattern.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/06_transcript_replay.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/07_single_policy_correction.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/README.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/_util.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/integrations/README.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/integrations/litellm/README.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/integrations/litellm/basic.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/integrations/litellm/with_preprocessor.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/integrations/litellm_proxy/README.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/integrations/litellm_proxy/config.example.yaml +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/integrations/litellm_proxy/context_compiler_precall_hook.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/examples/integrations/litellm_proxy/context_compiler_precall_hook_with_preprocessor.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/experimental/__init__.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/experimental/preprocessor/README.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/experimental/preprocessor/__init__.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/experimental/preprocessor/constants.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/experimental/preprocessor/heuristic_preprocessor.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/experimental/preprocessor/output_validation.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/experimental/preprocessor/prompt_utils.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/experimental/preprocessor/prompts/default.txt +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/experimental/preprocessor/prompts/llama.txt +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/host_support/__init__.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/host_support/confirmation.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/host_support/provider_mode.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/src/context_compiler/__init__.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/src/context_compiler/const.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/src/context_compiler/controller.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/src/context_compiler/decision_constants.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/src/context_compiler/engine.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/src/context_compiler/repl.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/README.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/api/public-api-v1.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/001_import_checkpoint_non_object_rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/002_import_checkpoint_unsupported_version_rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/003_import_checkpoint_invalid_pending_shape_rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/004_import_checkpoint_invalid_replacement_shape_rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/005_import_checkpoint_invalid_authoritative_state_rejected_atomically.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/006_import_checkpoint_pending_null_clears_existing_pending.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/checkpoint/007_import_checkpoint_pending_absent_clears_existing_pending.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/state-json/001_export_json_canonical_sorted_compact.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/state-json/002_import_json_invalid_json_rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/state-json/003_import_json_non_object_rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/state-json/004_import_json_unsupported_version_rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/state-json/005_import_json_empty_normalized_policy_key_rejected_atomically.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/state-json/006_import_json_valid_normalized_policy_key_accepted.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/001_set_premise_update.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/002_use_item_normalization.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/003_conflict_prohibit_clarify.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/004_remove_policy_missing_idempotent_update.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/005_exact_prefix_passthrough_leading_space.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/006_near_miss_set_premise_to.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/007_near_miss_change_premise_missing_to.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/008_replace_missing_source_clarify_prompt.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/009_pending_affirmative_normalized_token.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/010_pending_negative_normalized_token.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/011_pending_unmatched_reuses_prompt.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/012_clear_premise_populated_update.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/013_clear_premise_already_null_update.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/014_reset_policies_populated_update.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/015_reset_policies_already_empty_update.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/016_clear_state_populated_update.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/017_clear_state_already_empty_update.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/018_pending_affirmative_punctuation_token.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/step/019_pending_negative_punctuation_token.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/transcript/001_user_only_replay_state.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/transcript/002_non_string_user_content_ignored.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/transcript/003_stops_at_first_clarify_later_yes.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/conformance/transcript/004_stops_at_first_clarify_later_no.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/controller/preview_clarify_no_mutation.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/controller/preview_idempotent_no_mutation.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/README.md +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/expected/contradiction_clarify.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/expected/pending_clarify_no.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/expected/pending_clarify_unmatched.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/expected/pending_clarify_yes.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/expected/premise_lifecycle.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/expected/replacement_clarify.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/scenarios/contradiction_clarify.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/scenarios/pending_clarify_no.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/scenarios/pending_clarify_unmatched.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/scenarios/pending_clarify_yes.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/scenarios/premise_lifecycle.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/engine-regression/structured/scenarios/replacement_clarify.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/admin-alias-remove-policies-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/admin-alias-reset-policy-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/ambiguous-directive-adjacent.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-bracket-wrapper.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-case-normalized-use-docker.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-clear-state-period.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-clear-state.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-paren-wrapper.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-prohibit-peanuts.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-quoted-payload-use-docker.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-reset-policies-bang.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/canonical-directive-whitespace-collapsed-use-docker.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/fenced-code-block-directive-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/inline-prose-code-directive-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/list-prefix-directive-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/malformed-replacement-instead-docker-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/meta-prefix-directive-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/mixed-directive-task-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/mixed-intent-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/modal-please-clear-state-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/multiline-multi-directive-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/natural-language-dont-use-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-change-premise-missing-to-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-change-premise-to-empty-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-prohibit-empty-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-remove-policy-empty-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-set-premise-empty-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-set-premise-to-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-use-empty-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-use-instead-of-missing-new-item-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/near-miss-use-instead-of-missing-old-item-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/nested-wrapper-clear-state-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/ordinary-non-directive.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-fenced-code-rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-inline-prose-code-rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-mixed-directive-task-rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-multiline-rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-question-form-rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-quoted-payload-locked.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-reported-speech-rejected.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-safe-canonical-use-docker.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/parse-source-input-safe-canonicalization-use-docker.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/public-api-v1.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/question-can-you-use-docker-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/question-use-docker-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/quoted-exact-use-docker-backtick-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/quoted-exact-use-docker-single-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/quoted-exact-use-docker-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/quoted-reported-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/reported-speech-docs-say-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/sentence-adjacent-directive-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/unsupported-alias-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-invalid-json-shape-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-malformed-json-text-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-malformed-sentinel-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-malformed-text-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-multi-candidate-directive-unknown.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-sentinel-no-directive.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-source-input-allow-safe-directive.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-source-input-block-change-premise-rewrite.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-source-input-block-set-premise-rewrite.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/fixtures/preprocessor/validator-structured-json-directive.json +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_04_grammar_edge_cases.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_04_llm_tool_governance.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_07_llm_prompt_engineering_comparison.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_api_contract_fixture.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_controller.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_decision_constants.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_demo_01_04_behavior.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_demo_05_prompt_contract.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_demo_07_output_clarity.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_demo_08_09_behavior.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_demo_compaction.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_demo_oracle_properties.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_engine.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_example_integrations_imports.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_examples.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_examples_behavior.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_examples_smoke.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_fixtures.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_host_confirmation.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_host_observability.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_litellm_checkpoint_integration.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_litellm_integration_error_paths.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_litellm_preprocessor_model_config.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_llm_client.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_llm_demos.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_precompiler_prompt_utils.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_preprocessor_api_contract_fixture.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_preprocessor_conformance.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_preprocessor_heuristic.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_preprocessor_heuristic_properties.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_preprocessor_output_validation.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_preprocessor_validator_properties.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_properties.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_provider_helper.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_repl.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_repl_coverage.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_repl_properties.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_run_demo.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_smoke.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_structured_regression.py +0 -0
- {context_compiler-0.7.1 → context_compiler-0.7.2}/tests/test_transcript_replay.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: context-compiler
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: Deterministic conversational state engine for LLM applications.
|
|
5
5
|
Project-URL: Homepage, https://github.com/rlippmann/context-compiler
|
|
6
6
|
Project-URL: Repository, https://github.com/rlippmann/context-compiler
|
|
@@ -18,7 +18,7 @@ These examples support both sync (`0.8.x`) and async (`0.9.x`) user lookup.
|
|
|
18
18
|
The minimal pipe path below is the easiest first-run flow and was runtime-validated in Docker via API flow with a real backend model.
|
|
19
19
|
|
|
20
20
|
1. Import `open_webui_pipe.py` (recommended/default) as a Function by URL.
|
|
21
|
-
2. Open WebUI installs `context-compiler>=0.7.
|
|
21
|
+
2. Open WebUI installs `context-compiler>=0.7.2` from the function frontmatter requirements.
|
|
22
22
|
3. Enable the function.
|
|
23
23
|
4. Set `BASE_MODEL_ID` to a valid Open WebUI model id (required).
|
|
24
24
|
5. Select the pipe model in chat.
|
|
@@ -27,7 +27,7 @@ Open WebUI is a separate runtime and must already be installed/configured separa
|
|
|
27
27
|
Open WebUI also needs at least one real backend model/provider configured (for example Ollama or OpenAI) so `BASE_MODEL_ID` resolves to an actual model.
|
|
28
28
|
Note: The `PROVIDER` environment contract used in LiteLLM examples/demos does not apply to OpenWebUI. OpenWebUI manages providers via its own connection settings and model IDs.
|
|
29
29
|
|
|
30
|
-
Checkpoint continuation in these examples requires `context-compiler>=0.7.
|
|
30
|
+
Checkpoint continuation in these examples requires `context-compiler>=0.7.2`.
|
|
31
31
|
|
|
32
32
|
### Model configuration
|
|
33
33
|
|
|
@@ -64,8 +64,8 @@ If frontmatter dependency installs are disabled, offline, or unavailable:
|
|
|
64
64
|
1. Open a shell in the Open WebUI container:
|
|
65
65
|
- `docker exec -it <openwebui-container> sh`
|
|
66
66
|
2. Install the package manually:
|
|
67
|
-
- Minimal pipe: `pip install "context-compiler>=0.7.
|
|
68
|
-
- Preprocessor pipe: `pip install "context-compiler[experimental]>=0.7.
|
|
67
|
+
- Minimal pipe: `pip install "context-compiler>=0.7.2"`
|
|
68
|
+
- Preprocessor pipe: `pip install "context-compiler[experimental]>=0.7.2"`
|
|
69
69
|
3. Import and enable the function in Open WebUI, then configure valves.
|
|
70
70
|
|
|
71
71
|
### Finding valid model ids
|
{context_compiler-0.7.1 → context_compiler-0.7.2}/examples/integrations/openwebui/open_webui_pipe.py
RENAMED
|
@@ -3,8 +3,8 @@ title: Context Compiler Pipe
|
|
|
3
3
|
author: rlippmann
|
|
4
4
|
author_url: https://github.com/rlippmann/context-compiler
|
|
5
5
|
funding_url: https://github.com/rlippmann/context-compiler
|
|
6
|
-
version: 0.9.
|
|
7
|
-
requirements: context-compiler>=0.7.
|
|
6
|
+
version: 0.9.1
|
|
7
|
+
requirements: context-compiler>=0.7.2
|
|
8
8
|
|
|
9
9
|
Minimal Open WebUI Pipe integration for Context Compiler.
|
|
10
10
|
|
|
@@ -193,6 +193,12 @@ def _normalize_state(value: object) -> State:
|
|
|
193
193
|
return {"premise": None, "policies": {}, "version": 2}
|
|
194
194
|
|
|
195
195
|
|
|
196
|
+
def _has_non_empty_authoritative_state(state: State) -> bool:
|
|
197
|
+
if get_premise_value(state) is not None:
|
|
198
|
+
return True
|
|
199
|
+
return bool(get_policy_items(state, "use") or get_policy_items(state, "prohibit"))
|
|
200
|
+
|
|
201
|
+
|
|
196
202
|
def _build_compact_trace_text(
|
|
197
203
|
*,
|
|
198
204
|
decision: object,
|
|
@@ -229,6 +235,25 @@ def _strip_trace_blocks_from_messages(messages: list[dict[str, Any]]) -> list[di
|
|
|
229
235
|
return cleaned
|
|
230
236
|
|
|
231
237
|
|
|
238
|
+
def _build_forward_messages(
|
|
239
|
+
raw_messages: object,
|
|
240
|
+
*,
|
|
241
|
+
state: State | None = None,
|
|
242
|
+
) -> list[dict[str, Any]]:
|
|
243
|
+
"""Build forwarded messages with trace stripping and optional state injection."""
|
|
244
|
+
messages = (
|
|
245
|
+
_strip_trace_blocks_from_messages([msg for msg in raw_messages if isinstance(msg, dict)])
|
|
246
|
+
if isinstance(raw_messages, list)
|
|
247
|
+
else []
|
|
248
|
+
)
|
|
249
|
+
if state is not None and _has_non_empty_authoritative_state(state):
|
|
250
|
+
return _replace_compiler_system_message(
|
|
251
|
+
messages,
|
|
252
|
+
_render_compiler_state_block(state),
|
|
253
|
+
)
|
|
254
|
+
return messages
|
|
255
|
+
|
|
256
|
+
|
|
232
257
|
def _strip_existing_trace_from_chunk(chunk: object) -> object:
|
|
233
258
|
if isinstance(chunk, str):
|
|
234
259
|
return _strip_trace_block_from_text(chunk)
|
|
@@ -475,15 +500,13 @@ class Pipe:
|
|
|
475
500
|
body: dict[str, Any],
|
|
476
501
|
user_payload: dict[str, Any],
|
|
477
502
|
request: Request,
|
|
503
|
+
*,
|
|
504
|
+
state: State | None = None,
|
|
478
505
|
) -> Any:
|
|
479
|
-
"""Forward with
|
|
506
|
+
"""Forward with model override and optional compiler-owned state injection."""
|
|
480
507
|
payload = {**body}
|
|
481
508
|
payload["model"] = self.valves.BASE_MODEL_ID
|
|
482
|
-
|
|
483
|
-
if isinstance(raw_messages, list):
|
|
484
|
-
payload["messages"] = _strip_trace_blocks_from_messages(
|
|
485
|
-
[msg for msg in raw_messages if isinstance(msg, dict)]
|
|
486
|
-
)
|
|
509
|
+
payload["messages"] = _build_forward_messages(body.get("messages"), state=state)
|
|
487
510
|
user = Users.get_user_by_id(user_payload["id"])
|
|
488
511
|
if inspect.isawaitable(user):
|
|
489
512
|
user = await user
|
|
@@ -514,18 +537,7 @@ class Pipe:
|
|
|
514
537
|
payload = {**body}
|
|
515
538
|
payload["model"] = self.valves.BASE_MODEL_ID
|
|
516
539
|
|
|
517
|
-
|
|
518
|
-
messages = (
|
|
519
|
-
_strip_trace_blocks_from_messages(
|
|
520
|
-
[msg for msg in raw_messages if isinstance(msg, dict)]
|
|
521
|
-
)
|
|
522
|
-
if isinstance(raw_messages, list)
|
|
523
|
-
else []
|
|
524
|
-
)
|
|
525
|
-
payload["messages"] = _replace_compiler_system_message(
|
|
526
|
-
messages,
|
|
527
|
-
_render_compiler_state_block(state),
|
|
528
|
-
)
|
|
540
|
+
payload["messages"] = _build_forward_messages(body.get("messages"), state=state)
|
|
529
541
|
|
|
530
542
|
user = Users.get_user_by_id(user_payload["id"])
|
|
531
543
|
if inspect.isawaitable(user):
|
|
@@ -625,7 +637,11 @@ class Pipe:
|
|
|
625
637
|
llm_called=False,
|
|
626
638
|
)
|
|
627
639
|
if kind == DECISION_PASSTHROUGH:
|
|
628
|
-
|
|
640
|
+
compiled_state = _normalize_state(state_after)
|
|
641
|
+
state_injected = "yes" if _has_non_empty_authoritative_state(compiled_state) else "no"
|
|
642
|
+
response = await self._forward_passthrough(
|
|
643
|
+
body, __user__, __request__, state=compiled_state
|
|
644
|
+
)
|
|
629
645
|
return self._with_trace(
|
|
630
646
|
response,
|
|
631
647
|
original_input=latest_user_text,
|
|
@@ -634,6 +650,7 @@ class Pipe:
|
|
|
634
650
|
state_before=state_before,
|
|
635
651
|
state_after=state_after,
|
|
636
652
|
llm_called=True,
|
|
653
|
+
state_injected=state_injected,
|
|
637
654
|
)
|
|
638
655
|
if kind == DECISION_UPDATE:
|
|
639
656
|
_CHECKPOINTS_BY_CHAT_KEY[chat_key] = engine.export_checkpoint_json()
|
|
@@ -647,7 +664,11 @@ class Pipe:
|
|
|
647
664
|
llm_called=False,
|
|
648
665
|
)
|
|
649
666
|
|
|
650
|
-
|
|
667
|
+
compiled_state = _normalize_state(state_after)
|
|
668
|
+
state_injected = "yes" if _has_non_empty_authoritative_state(compiled_state) else "no"
|
|
669
|
+
response = await self._forward_passthrough(
|
|
670
|
+
body, __user__, __request__, state=compiled_state
|
|
671
|
+
)
|
|
651
672
|
return self._with_trace(
|
|
652
673
|
response,
|
|
653
674
|
original_input=latest_user_text,
|
|
@@ -656,4 +677,5 @@ class Pipe:
|
|
|
656
677
|
state_before=state_before,
|
|
657
678
|
state_after=state_after,
|
|
658
679
|
llm_called=True,
|
|
680
|
+
state_injected=state_injected,
|
|
659
681
|
)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"""
|
|
2
|
-
title: Context Compiler Preprocessor
|
|
2
|
+
title: Context Compiler Pipe (Preprocessor)
|
|
3
3
|
author: rlippmann
|
|
4
4
|
author_url: https://github.com/rlippmann/context-compiler
|
|
5
5
|
funding_url: https://github.com/rlippmann/context-compiler
|
|
6
|
-
version: 0.9.
|
|
7
|
-
requirements: context-compiler[experimental]>=0.7.
|
|
6
|
+
version: 0.9.1
|
|
7
|
+
requirements: context-compiler[experimental]>=0.7.2
|
|
8
8
|
|
|
9
9
|
Open WebUI integration with Context Compiler preprocessor.
|
|
10
10
|
|
|
@@ -198,6 +198,12 @@ def _normalize_state(value: object) -> State:
|
|
|
198
198
|
return {"premise": None, "policies": {}, "version": 2}
|
|
199
199
|
|
|
200
200
|
|
|
201
|
+
def _has_non_empty_authoritative_state(state: State) -> bool:
|
|
202
|
+
if get_premise_value(state) is not None:
|
|
203
|
+
return True
|
|
204
|
+
return bool(get_policy_items(state, "use") or get_policy_items(state, "prohibit"))
|
|
205
|
+
|
|
206
|
+
|
|
201
207
|
def _build_compact_trace_text(
|
|
202
208
|
*,
|
|
203
209
|
decision: object,
|
|
@@ -234,6 +240,25 @@ def _strip_trace_blocks_from_messages(messages: list[dict[str, Any]]) -> list[di
|
|
|
234
240
|
return cleaned
|
|
235
241
|
|
|
236
242
|
|
|
243
|
+
def _build_forward_messages(
|
|
244
|
+
raw_messages: object,
|
|
245
|
+
*,
|
|
246
|
+
state: State | None = None,
|
|
247
|
+
) -> list[dict[str, Any]]:
|
|
248
|
+
"""Build forwarded messages with trace stripping and optional state injection."""
|
|
249
|
+
messages = (
|
|
250
|
+
_strip_trace_blocks_from_messages([msg for msg in raw_messages if isinstance(msg, dict)])
|
|
251
|
+
if isinstance(raw_messages, list)
|
|
252
|
+
else []
|
|
253
|
+
)
|
|
254
|
+
if state is not None and _has_non_empty_authoritative_state(state):
|
|
255
|
+
return _replace_compiler_system_message(
|
|
256
|
+
messages,
|
|
257
|
+
_render_compiler_state_block(state),
|
|
258
|
+
)
|
|
259
|
+
return messages
|
|
260
|
+
|
|
261
|
+
|
|
237
262
|
def _strip_existing_trace_from_chunk(chunk: object) -> object:
|
|
238
263
|
if isinstance(chunk, str):
|
|
239
264
|
return _strip_trace_block_from_text(chunk)
|
|
@@ -693,6 +718,7 @@ class Pipe:
|
|
|
693
718
|
request: Request,
|
|
694
719
|
*,
|
|
695
720
|
base_model_id: str | None,
|
|
721
|
+
state: State | None = None,
|
|
696
722
|
) -> Any:
|
|
697
723
|
if base_model_id is None:
|
|
698
724
|
if self._allow_missing_base_model_for_debug():
|
|
@@ -706,11 +732,7 @@ class Pipe:
|
|
|
706
732
|
)
|
|
707
733
|
payload = {**body}
|
|
708
734
|
payload["model"] = base_model_id
|
|
709
|
-
|
|
710
|
-
if isinstance(raw_messages, list):
|
|
711
|
-
payload["messages"] = _strip_trace_blocks_from_messages(
|
|
712
|
-
[msg for msg in raw_messages if isinstance(msg, dict)]
|
|
713
|
-
)
|
|
735
|
+
payload["messages"] = _build_forward_messages(body.get("messages"), state=state)
|
|
714
736
|
user = Users.get_user_by_id(user_payload["id"])
|
|
715
737
|
if inspect.isawaitable(user):
|
|
716
738
|
user = await user
|
|
@@ -748,18 +770,7 @@ class Pipe:
|
|
|
748
770
|
payload = {**body}
|
|
749
771
|
payload["model"] = base_model_id
|
|
750
772
|
|
|
751
|
-
|
|
752
|
-
messages = (
|
|
753
|
-
_strip_trace_blocks_from_messages(
|
|
754
|
-
[msg for msg in raw_messages if isinstance(msg, dict)]
|
|
755
|
-
)
|
|
756
|
-
if isinstance(raw_messages, list)
|
|
757
|
-
else []
|
|
758
|
-
)
|
|
759
|
-
payload["messages"] = _replace_compiler_system_message(
|
|
760
|
-
messages,
|
|
761
|
-
_render_compiler_state_block(state),
|
|
762
|
-
)
|
|
773
|
+
payload["messages"] = _build_forward_messages(body.get("messages"), state=state)
|
|
763
774
|
|
|
764
775
|
user = Users.get_user_by_id(user_payload["id"])
|
|
765
776
|
if inspect.isawaitable(user):
|
|
@@ -906,11 +917,14 @@ class Pipe:
|
|
|
906
917
|
llm_called=False,
|
|
907
918
|
)
|
|
908
919
|
if kind == DECISION_PASSTHROUGH:
|
|
920
|
+
compiled_state = _normalize_state(state_after)
|
|
921
|
+
state_injected = "yes" if _has_non_empty_authoritative_state(compiled_state) else "no"
|
|
909
922
|
response = await self._forward_passthrough(
|
|
910
923
|
body,
|
|
911
924
|
__user__,
|
|
912
925
|
__request__,
|
|
913
926
|
base_model_id=base_model_id,
|
|
927
|
+
state=compiled_state,
|
|
914
928
|
)
|
|
915
929
|
return self._with_trace(
|
|
916
930
|
response,
|
|
@@ -921,6 +935,7 @@ class Pipe:
|
|
|
921
935
|
state_after=state_after,
|
|
922
936
|
preprocessor_output=preprocessd,
|
|
923
937
|
llm_called=base_model_id is not None,
|
|
938
|
+
state_injected=state_injected,
|
|
924
939
|
)
|
|
925
940
|
if kind == DECISION_UPDATE:
|
|
926
941
|
_CHECKPOINTS_BY_CHAT_KEY[chat_key] = engine.export_checkpoint_json()
|
|
@@ -935,11 +950,14 @@ class Pipe:
|
|
|
935
950
|
llm_called=False,
|
|
936
951
|
)
|
|
937
952
|
|
|
953
|
+
compiled_state = _normalize_state(state_after)
|
|
954
|
+
state_injected = "yes" if _has_non_empty_authoritative_state(compiled_state) else "no"
|
|
938
955
|
response = await self._forward_passthrough(
|
|
939
956
|
body,
|
|
940
957
|
__user__,
|
|
941
958
|
__request__,
|
|
942
959
|
base_model_id=base_model_id,
|
|
960
|
+
state=compiled_state,
|
|
943
961
|
)
|
|
944
962
|
return self._with_trace(
|
|
945
963
|
response,
|
|
@@ -950,4 +968,5 @@ class Pipe:
|
|
|
950
968
|
state_after=state_after,
|
|
951
969
|
preprocessor_output=preprocessd,
|
|
952
970
|
llm_called=base_model_id is not None,
|
|
971
|
+
state_injected=state_injected,
|
|
953
972
|
)
|
|
@@ -162,7 +162,7 @@ def build_compact_trace_text(
|
|
|
162
162
|
|
|
163
163
|
lines.append(f"active state: {_active_state_summary(state_after)}")
|
|
164
164
|
lines.append(f"downstream LLM call: {'yes' if llm_called else 'no'}")
|
|
165
|
-
lines.append("state injected:
|
|
165
|
+
lines.append(f"state injected: {state_injected}")
|
|
166
166
|
return "\n".join(lines)
|
|
167
167
|
|
|
168
168
|
|
|
@@ -615,6 +615,56 @@ def test_pipe_near_miss_directives_return_deterministic_clarify_without_downstre
|
|
|
615
615
|
assert downstream_calls == 0
|
|
616
616
|
|
|
617
617
|
|
|
618
|
+
def test_pipe_incomplete_replacement_clarify_has_no_model_call(monkeypatch) -> None:
|
|
619
|
+
module = _load_module_with_openwebui_stubs(
|
|
620
|
+
"owui_pipe_incomplete_replacement_clarify", monkeypatch
|
|
621
|
+
)
|
|
622
|
+
module._ENGINES_BY_CHAT_KEY.clear()
|
|
623
|
+
module._CHECKPOINTS_BY_CHAT_KEY.clear()
|
|
624
|
+
|
|
625
|
+
downstream_calls = 0
|
|
626
|
+
|
|
627
|
+
async def _track_downstream(
|
|
628
|
+
_: object, payload: dict[str, object], __: object
|
|
629
|
+
) -> dict[str, object]:
|
|
630
|
+
nonlocal downstream_calls
|
|
631
|
+
downstream_calls += 1
|
|
632
|
+
raise AssertionError(f"downstream model should not be called: {payload.get('model')}")
|
|
633
|
+
|
|
634
|
+
module.generate_chat_completion = _track_downstream
|
|
635
|
+
|
|
636
|
+
pipe = module.Pipe()
|
|
637
|
+
pipe.valves.BASE_MODEL_ID = "base-model"
|
|
638
|
+
chat_id = "chat-incomplete-replacement-clarify"
|
|
639
|
+
|
|
640
|
+
result = asyncio.run(
|
|
641
|
+
pipe.pipe(
|
|
642
|
+
{
|
|
643
|
+
"model": "pipe-model",
|
|
644
|
+
"messages": [{"role": "user", "content": "use docker instead of"}],
|
|
645
|
+
},
|
|
646
|
+
__user__={"id": "u1"},
|
|
647
|
+
__request__=object(),
|
|
648
|
+
__chat_id__=chat_id,
|
|
649
|
+
)
|
|
650
|
+
)
|
|
651
|
+
assert result == (
|
|
652
|
+
"Replacement requires both new and old items.\n"
|
|
653
|
+
"Use 'use <new item> instead of <old item>' with non-empty values."
|
|
654
|
+
)
|
|
655
|
+
assert downstream_calls == 0
|
|
656
|
+
|
|
657
|
+
state_view = asyncio.run(
|
|
658
|
+
pipe.pipe(
|
|
659
|
+
{"model": "pipe-model", "messages": [{"role": "user", "content": "show state"}]},
|
|
660
|
+
__user__={"id": "u1"},
|
|
661
|
+
__request__=object(),
|
|
662
|
+
__chat_id__=chat_id,
|
|
663
|
+
)
|
|
664
|
+
)
|
|
665
|
+
assert state_view == "Premise: none\nUse: none\nProhibit: none\nPending clarification: no"
|
|
666
|
+
|
|
667
|
+
|
|
618
668
|
@pytest.mark.parametrize(
|
|
619
669
|
("confirmation", "expected_policies"),
|
|
620
670
|
[
|
|
@@ -1186,3 +1236,159 @@ def test_pipe_clear_state_strips_preexisting_contradictory_trace_from_model_outp
|
|
|
1186
1236
|
assert second_content.count("Context Compiler trace") == 1
|
|
1187
1237
|
assert "downstream LLM call: no" in second_content
|
|
1188
1238
|
assert "downstream LLM call: yes" not in second_content
|
|
1239
|
+
|
|
1240
|
+
|
|
1241
|
+
def test_pipe_passthrough_injects_active_state_and_trace_reports_yes(monkeypatch) -> None:
|
|
1242
|
+
module = _load_module_with_openwebui_stubs("owui_pipe_passthrough_state_injection", monkeypatch)
|
|
1243
|
+
module._ENGINES_BY_CHAT_KEY.clear()
|
|
1244
|
+
module._CHECKPOINTS_BY_CHAT_KEY.clear()
|
|
1245
|
+
|
|
1246
|
+
forwarded_payloads: list[dict[str, object]] = []
|
|
1247
|
+
|
|
1248
|
+
async def _chat_completion(
|
|
1249
|
+
_: object, payload: dict[str, object], __: object
|
|
1250
|
+
) -> dict[str, object]:
|
|
1251
|
+
forwarded_payloads.append(payload)
|
|
1252
|
+
return {"choices": [{"message": {"content": "answer"}}]}
|
|
1253
|
+
|
|
1254
|
+
monkeypatch.setattr(module, "generate_chat_completion", _chat_completion)
|
|
1255
|
+
|
|
1256
|
+
pipe = module.Pipe()
|
|
1257
|
+
pipe.valves.BASE_MODEL_ID = "base-model"
|
|
1258
|
+
pipe.valves.SHOW_CONTEXT_COMPILER_TRACE = True
|
|
1259
|
+
chat_id = "chat-passthrough-injected-state"
|
|
1260
|
+
|
|
1261
|
+
update = asyncio.run(
|
|
1262
|
+
pipe.pipe(
|
|
1263
|
+
{"model": "pipe-model", "messages": [{"role": "user", "content": "use docker"}]},
|
|
1264
|
+
__user__={"id": "u1"},
|
|
1265
|
+
__request__=object(),
|
|
1266
|
+
__chat_id__=chat_id,
|
|
1267
|
+
)
|
|
1268
|
+
)
|
|
1269
|
+
assert "State updated: Use docker." in update
|
|
1270
|
+
assert len(forwarded_payloads) == 0
|
|
1271
|
+
|
|
1272
|
+
passthrough = asyncio.run(
|
|
1273
|
+
pipe.pipe(
|
|
1274
|
+
{
|
|
1275
|
+
"model": "pipe-model",
|
|
1276
|
+
"messages": [{"role": "user", "content": "what container runtime should i use?"}],
|
|
1277
|
+
},
|
|
1278
|
+
__user__={"id": "u1"},
|
|
1279
|
+
__request__=object(),
|
|
1280
|
+
__chat_id__=chat_id,
|
|
1281
|
+
)
|
|
1282
|
+
)
|
|
1283
|
+
assert isinstance(passthrough, dict)
|
|
1284
|
+
assert len(forwarded_payloads) == 1
|
|
1285
|
+
messages = forwarded_payloads[0]["messages"]
|
|
1286
|
+
assert isinstance(messages, list)
|
|
1287
|
+
assert any(
|
|
1288
|
+
isinstance(msg, dict)
|
|
1289
|
+
and msg.get("role") == "system"
|
|
1290
|
+
and isinstance(msg.get("content"), str)
|
|
1291
|
+
and msg["content"].startswith("[[cc_state]]")
|
|
1292
|
+
and "Use: docker" in msg["content"]
|
|
1293
|
+
for msg in messages
|
|
1294
|
+
)
|
|
1295
|
+
content = passthrough["choices"][0]["message"]["content"]
|
|
1296
|
+
assert "state injected: yes" in content
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
def test_pipe_empty_state_passthrough_does_not_inject_and_trace_reports_no(monkeypatch) -> None:
|
|
1300
|
+
module = _load_module_with_openwebui_stubs("owui_pipe_empty_state_passthrough", monkeypatch)
|
|
1301
|
+
module._ENGINES_BY_CHAT_KEY.clear()
|
|
1302
|
+
module._CHECKPOINTS_BY_CHAT_KEY.clear()
|
|
1303
|
+
|
|
1304
|
+
forwarded_payloads: list[dict[str, object]] = []
|
|
1305
|
+
|
|
1306
|
+
async def _chat_completion(
|
|
1307
|
+
_: object, payload: dict[str, object], __: object
|
|
1308
|
+
) -> dict[str, object]:
|
|
1309
|
+
forwarded_payloads.append(payload)
|
|
1310
|
+
return {"choices": [{"message": {"content": "answer"}}]}
|
|
1311
|
+
|
|
1312
|
+
monkeypatch.setattr(module, "generate_chat_completion", _chat_completion)
|
|
1313
|
+
|
|
1314
|
+
pipe = module.Pipe()
|
|
1315
|
+
pipe.valves.BASE_MODEL_ID = "base-model"
|
|
1316
|
+
pipe.valves.SHOW_CONTEXT_COMPILER_TRACE = True
|
|
1317
|
+
|
|
1318
|
+
passthrough = asyncio.run(
|
|
1319
|
+
pipe.pipe(
|
|
1320
|
+
{"model": "pipe-model", "messages": [{"role": "user", "content": "hello"}]},
|
|
1321
|
+
__user__={"id": "u1"},
|
|
1322
|
+
__request__=object(),
|
|
1323
|
+
__chat_id__="chat-empty-state-passthrough",
|
|
1324
|
+
)
|
|
1325
|
+
)
|
|
1326
|
+
assert isinstance(passthrough, dict)
|
|
1327
|
+
assert len(forwarded_payloads) == 1
|
|
1328
|
+
messages = forwarded_payloads[0]["messages"]
|
|
1329
|
+
assert isinstance(messages, list)
|
|
1330
|
+
assert not any(
|
|
1331
|
+
isinstance(msg, dict)
|
|
1332
|
+
and msg.get("role") == "system"
|
|
1333
|
+
and isinstance(msg.get("content"), str)
|
|
1334
|
+
and msg["content"].startswith("[[cc_state]]")
|
|
1335
|
+
for msg in messages
|
|
1336
|
+
)
|
|
1337
|
+
content = passthrough["choices"][0]["message"]["content"]
|
|
1338
|
+
assert "downstream LLM call: yes" in content
|
|
1339
|
+
assert "state injected: no" in content
|
|
1340
|
+
|
|
1341
|
+
|
|
1342
|
+
def test_pipe_repeated_passthrough_does_not_duplicate_compiler_state_prompt(monkeypatch) -> None:
|
|
1343
|
+
module = _load_module_with_openwebui_stubs("owui_pipe_repeated_passthrough_no_dup", monkeypatch)
|
|
1344
|
+
module._ENGINES_BY_CHAT_KEY.clear()
|
|
1345
|
+
module._CHECKPOINTS_BY_CHAT_KEY.clear()
|
|
1346
|
+
|
|
1347
|
+
forwarded_payloads: list[dict[str, object]] = []
|
|
1348
|
+
|
|
1349
|
+
async def _chat_completion(
|
|
1350
|
+
_: object, payload: dict[str, object], __: object
|
|
1351
|
+
) -> dict[str, object]:
|
|
1352
|
+
forwarded_payloads.append(payload)
|
|
1353
|
+
return {"choices": [{"message": {"content": "answer"}}]}
|
|
1354
|
+
|
|
1355
|
+
monkeypatch.setattr(module, "generate_chat_completion", _chat_completion)
|
|
1356
|
+
|
|
1357
|
+
pipe = module.Pipe()
|
|
1358
|
+
pipe.valves.BASE_MODEL_ID = "base-model"
|
|
1359
|
+
chat_id = "chat-repeated-passthrough-no-dup"
|
|
1360
|
+
|
|
1361
|
+
_ = asyncio.run(
|
|
1362
|
+
pipe.pipe(
|
|
1363
|
+
{"model": "pipe-model", "messages": [{"role": "user", "content": "use docker"}]},
|
|
1364
|
+
__user__={"id": "u1"},
|
|
1365
|
+
__request__=object(),
|
|
1366
|
+
__chat_id__=chat_id,
|
|
1367
|
+
)
|
|
1368
|
+
)
|
|
1369
|
+
for idx in range(2):
|
|
1370
|
+
_ = asyncio.run(
|
|
1371
|
+
pipe.pipe(
|
|
1372
|
+
{
|
|
1373
|
+
"model": "pipe-model",
|
|
1374
|
+
"messages": [{"role": "user", "content": f"question {idx}"}],
|
|
1375
|
+
},
|
|
1376
|
+
__user__={"id": "u1"},
|
|
1377
|
+
__request__=object(),
|
|
1378
|
+
__chat_id__=chat_id,
|
|
1379
|
+
)
|
|
1380
|
+
)
|
|
1381
|
+
|
|
1382
|
+
assert len(forwarded_payloads) == 2
|
|
1383
|
+
for payload in forwarded_payloads:
|
|
1384
|
+
messages = payload.get("messages")
|
|
1385
|
+
assert isinstance(messages, list)
|
|
1386
|
+
cc_messages = [
|
|
1387
|
+
msg
|
|
1388
|
+
for msg in messages
|
|
1389
|
+
if isinstance(msg, dict)
|
|
1390
|
+
and msg.get("role") == "system"
|
|
1391
|
+
and isinstance(msg.get("content"), str)
|
|
1392
|
+
and msg["content"].startswith("[[cc_state]]")
|
|
1393
|
+
]
|
|
1394
|
+
assert len(cc_messages) == 1
|