context-compiler-example-integrations 0.1.0__py3-none-any.whl

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.
Files changed (65) hide show
  1. context_compiler_example_integrations/README.md +71 -0
  2. context_compiler_example_integrations/__init__.py +1 -0
  3. context_compiler_example_integrations/examples/__init__.py +12 -0
  4. context_compiler_example_integrations/examples/_shared/__init__.py +1 -0
  5. context_compiler_example_integrations/examples/_shared/litellm_request.py +61 -0
  6. context_compiler_example_integrations/examples/_shared/provider_mode.py +91 -0
  7. context_compiler_example_integrations/examples/checkpoint_continuation/README.md +77 -0
  8. context_compiler_example_integrations/examples/checkpoint_continuation/example.py +169 -0
  9. context_compiler_example_integrations/examples/checkpoint_continuation/fastapi/README.md +85 -0
  10. context_compiler_example_integrations/examples/checkpoint_continuation/fastapi/app.py +205 -0
  11. context_compiler_example_integrations/examples/execution_authorization/README.md +31 -0
  12. context_compiler_example_integrations/examples/execution_authorization/expense_approval/README.md +77 -0
  13. context_compiler_example_integrations/examples/execution_authorization/expense_approval/__init__.py +1 -0
  14. context_compiler_example_integrations/examples/execution_authorization/expense_approval/example.py +168 -0
  15. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/README.md +97 -0
  16. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/__init__.py +1 -0
  17. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/app.py +312 -0
  18. context_compiler_example_integrations/examples/execution_authorization/expense_approval/fastapi/model_approval.py +98 -0
  19. context_compiler_example_integrations/examples/gateway_middleware/README.md +49 -0
  20. context_compiler_example_integrations/examples/gateway_middleware/customer_support_routing/README.md +40 -0
  21. context_compiler_example_integrations/examples/gateway_middleware/customer_support_routing/__init__.py +1 -0
  22. context_compiler_example_integrations/examples/gateway_middleware/customer_support_routing/example.py +220 -0
  23. context_compiler_example_integrations/examples/prompt_construction/README.md +27 -0
  24. context_compiler_example_integrations/examples/prompt_construction/litellm/README.md +197 -0
  25. context_compiler_example_integrations/examples/prompt_construction/litellm/basic.py +392 -0
  26. context_compiler_example_integrations/examples/prompt_construction/litellm/confirmation_helper.py +91 -0
  27. context_compiler_example_integrations/examples/prompt_construction/litellm/with_directive_drafter.py +524 -0
  28. context_compiler_example_integrations/examples/prompt_construction/writing_assistant/README.md +92 -0
  29. context_compiler_example_integrations/examples/prompt_construction/writing_assistant/__init__.py +1 -0
  30. context_compiler_example_integrations/examples/prompt_construction/writing_assistant/example.py +205 -0
  31. context_compiler_example_integrations/examples/retrieval_filtering/README.md +65 -0
  32. context_compiler_example_integrations/examples/retrieval_filtering/chromadb_hr_policy_lookup/README.md +120 -0
  33. context_compiler_example_integrations/examples/retrieval_filtering/chromadb_hr_policy_lookup/__init__.py +1 -0
  34. context_compiler_example_integrations/examples/retrieval_filtering/chromadb_hr_policy_lookup/example.py +320 -0
  35. context_compiler_example_integrations/examples/retrieval_filtering/hr_policy_lookup/README.md +123 -0
  36. context_compiler_example_integrations/examples/retrieval_filtering/hr_policy_lookup/__init__.py +1 -0
  37. context_compiler_example_integrations/examples/retrieval_filtering/hr_policy_lookup/example.py +300 -0
  38. context_compiler_example_integrations/examples/schema_selection/README.md +41 -0
  39. context_compiler_example_integrations/examples/schema_selection/litellm_response_format/response_format.py +218 -0
  40. context_compiler_example_integrations/examples/schema_selection/ollama_structured_output/README.md +60 -0
  41. context_compiler_example_integrations/examples/schema_selection/ollama_structured_output/example.py +171 -0
  42. context_compiler_example_integrations/examples/schema_selection/refund_intake/README.md +95 -0
  43. context_compiler_example_integrations/examples/schema_selection/refund_intake/__init__.py +1 -0
  44. context_compiler_example_integrations/examples/schema_selection/refund_intake/example.py +180 -0
  45. context_compiler_example_integrations/examples/tool_gating/README.md +55 -0
  46. context_compiler_example_integrations/examples/tool_gating/calendar_admin/README.md +34 -0
  47. context_compiler_example_integrations/examples/tool_gating/calendar_admin/__init__.py +1 -0
  48. context_compiler_example_integrations/examples/tool_gating/calendar_admin/example.py +195 -0
  49. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/README.md +93 -0
  50. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/__init__.py +1 -0
  51. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/example.py +250 -0
  52. context_compiler_example_integrations/examples/tool_gating/mcp_calendar_admin/live_model.py +369 -0
  53. context_compiler_example_integrations/reference_integrations/__init__.py +12 -0
  54. context_compiler_example_integrations/reference_integrations/litellm_proxy/README.md +251 -0
  55. context_compiler_example_integrations/reference_integrations/litellm_proxy/_checkpoint_support.py +146 -0
  56. context_compiler_example_integrations/reference_integrations/litellm_proxy/config.example.yaml +23 -0
  57. context_compiler_example_integrations/reference_integrations/litellm_proxy/context_compiler_precall_hook.py +163 -0
  58. context_compiler_example_integrations/reference_integrations/litellm_proxy/context_compiler_precall_hook_with_directive_drafter.py +289 -0
  59. context_compiler_example_integrations/reference_integrations/openwebui_pipe/README.md +233 -0
  60. context_compiler_example_integrations/reference_integrations/openwebui_pipe/open_webui_pipe.py +750 -0
  61. context_compiler_example_integrations/reference_integrations/openwebui_pipe/open_webui_pipe_with_directive_drafter.py +1045 -0
  62. context_compiler_example_integrations-0.1.0.dist-info/METADATA +110 -0
  63. context_compiler_example_integrations-0.1.0.dist-info/RECORD +65 -0
  64. context_compiler_example_integrations-0.1.0.dist-info/WHEEL +4 -0
  65. context_compiler_example_integrations-0.1.0.dist-info/licenses/LICENSE +173 -0
@@ -0,0 +1,171 @@
1
+ """Minimal host-side Ollama structured-output schema selection.
2
+
3
+ Flow:
4
+ Context Compiler state -> host selection logic -> Ollama `format` JSON Schema.
5
+
6
+ This example keeps model execution optional so tests can validate behavior without Ollama.
7
+ """
8
+
9
+ import json
10
+ import os
11
+ import urllib.error
12
+ import urllib.request
13
+ from collections.abc import Mapping
14
+ from typing import Any, TypedDict, cast
15
+
16
+ from context_compiler import (
17
+ POLICY_PROHIBIT,
18
+ POLICY_USE,
19
+ State,
20
+ create_engine,
21
+ get_clarify_prompt,
22
+ get_decision_state,
23
+ get_policy_items,
24
+ is_clarify,
25
+ )
26
+ from context_compiler.engine import Engine
27
+
28
+ PYTHON_SCRIPT_SCHEMA: dict[str, Any] = {
29
+ "type": "object",
30
+ "properties": {
31
+ "python_script": {
32
+ "type": "string",
33
+ "description": "A complete Python script.",
34
+ }
35
+ },
36
+ "required": ["python_script"],
37
+ "additionalProperties": False,
38
+ }
39
+
40
+ SHELL_COMMAND_SCHEMA: dict[str, Any] = {
41
+ "type": "object",
42
+ "properties": {
43
+ "shell_command": {
44
+ "type": "string",
45
+ "description": "A single shell command.",
46
+ }
47
+ },
48
+ "required": ["shell_command"],
49
+ "additionalProperties": False,
50
+ }
51
+
52
+ # Small, explicit mapping from policy item -> Ollama `format` schema.
53
+ _SCHEMA_BY_ITEM: dict[str, dict[str, Any]] = {
54
+ "python_script": PYTHON_SCRIPT_SCHEMA,
55
+ "shell_command": SHELL_COMMAND_SCHEMA,
56
+ }
57
+
58
+
59
+ class TurnPlan(TypedDict):
60
+ decision_kind: str
61
+ clarify_prompt: str | None
62
+ selected_schema_item: str | None
63
+ format_schema: dict[str, Any] | None
64
+
65
+
66
+ def select_ollama_format_schema(
67
+ state: State,
68
+ ) -> tuple[str | None, dict[str, Any] | None]:
69
+ """Return (policy_item, schema) or (None, None) when no safe match exists.
70
+
71
+ Unknown/insufficient policy state intentionally selects no schema.
72
+ """
73
+
74
+ use_items = set(get_policy_items(state, POLICY_USE))
75
+ prohibit_items = set(get_policy_items(state, POLICY_PROHIBIT))
76
+
77
+ for item, schema in _SCHEMA_BY_ITEM.items():
78
+ if item in use_items and item not in prohibit_items:
79
+ return item, schema
80
+
81
+ return None, None
82
+
83
+
84
+ def plan_turn(user_input: str, engine: Engine) -> TurnPlan:
85
+ """Run compiler step and decide whether to request Ollama structured output."""
86
+
87
+ decision = engine.step(user_input)
88
+ if is_clarify(decision):
89
+ return {
90
+ "decision_kind": "clarify",
91
+ "clarify_prompt": get_clarify_prompt(decision),
92
+ "selected_schema_item": None,
93
+ "format_schema": None,
94
+ }
95
+
96
+ decision_state = get_decision_state(decision)
97
+ compiled_state = decision_state if decision_state is not None else engine.state
98
+ selected_item, format_schema = select_ollama_format_schema(compiled_state)
99
+
100
+ return {
101
+ "decision_kind": str(decision["kind"]),
102
+ "clarify_prompt": None,
103
+ "selected_schema_item": selected_item,
104
+ "format_schema": format_schema,
105
+ }
106
+
107
+
108
+ def optional_ollama_call(
109
+ *,
110
+ user_input: str,
111
+ model: str,
112
+ format_schema: Mapping[str, Any] | None,
113
+ host: str | None = None,
114
+ ) -> dict[str, Any]:
115
+ """Optional smoke call to Ollama's /api/chat.
116
+
117
+ If `format_schema` is provided, it is passed through `format` exactly.
118
+ """
119
+
120
+ base_url = host or os.getenv("OLLAMA_BASE_URL") or "http://localhost:11434"
121
+ payload: dict[str, Any] = {
122
+ "model": model,
123
+ "messages": [{"role": "user", "content": user_input}],
124
+ "stream": False,
125
+ }
126
+ if format_schema is not None:
127
+ payload["format"] = dict(format_schema)
128
+
129
+ request = urllib.request.Request(
130
+ url=f"{base_url.rstrip('/')}/api/chat",
131
+ data=json.dumps(payload).encode("utf-8"),
132
+ headers={"Content-Type": "application/json"},
133
+ method="POST",
134
+ )
135
+
136
+ try:
137
+ with urllib.request.urlopen(request, timeout=30) as response:
138
+ raw = response.read().decode("utf-8")
139
+ except urllib.error.URLError as exc:
140
+ raise RuntimeError(f"Ollama call failed: {exc}") from exc
141
+
142
+ decoded = cast(object, json.loads(raw))
143
+ if not isinstance(decoded, dict):
144
+ raise RuntimeError("Ollama response must be a JSON object")
145
+ return cast(dict[str, Any], decoded)
146
+
147
+
148
+ def main() -> None:
149
+ engine = create_engine()
150
+
151
+ # Demonstration setup.
152
+ engine.step("use python_script")
153
+ engine.step("prohibit shell_command")
154
+
155
+ plan = plan_turn("Write a helper script to parse CSV files.", engine)
156
+ print("decision_kind:", plan["decision_kind"])
157
+ print("selected_schema_item:", plan["selected_schema_item"])
158
+ print("format_schema_selected:", plan["format_schema"] is not None)
159
+
160
+ # Optional model execution path; disabled by default.
161
+ if os.getenv("RUN_OLLAMA_SMOKE") == "1":
162
+ response = optional_ollama_call(
163
+ user_input="Write a helper script to parse CSV files.",
164
+ model=os.getenv("OLLAMA_MODEL", "llama3.1"),
165
+ format_schema=plan["format_schema"],
166
+ )
167
+ print("ollama_response_keys:", sorted(response.keys()))
168
+
169
+
170
+ if __name__ == "__main__":
171
+ main()
@@ -0,0 +1,95 @@
1
+ # Refund intake
2
+
3
+ Authoritative state changes which intake workflow the host selects for the same
4
+ ambiguous order request. This example shows two host-side schema-selection
5
+ mechanisms in a customer order/support intake flow.
6
+
7
+ The enforcement point stays the same:
8
+
9
+ - same user request
10
+ - different authoritative state
11
+ - different host-selected schema
12
+
13
+ Context Compiler does not choose the workflow by prompt wording. The host reads
14
+ the saved authoritative state and selects the workflow/schema from that state.
15
+ For premise-driven selection, the host applies a small deterministic
16
+ order-intake rule:
17
+
18
+ `saved order facts -> intake category -> selected schema`
19
+
20
+ In this example, the host checks for a few explicit order facts in the saved
21
+ premise, such as `delivered physical item` plus `damaged on arrival`, or
22
+ `digital subscription` plus `login failure`.
23
+
24
+ ## Enforcement point
25
+
26
+ Schema selection
27
+
28
+ ## State mechanisms
29
+
30
+ - policy-driven schema selection via `use ...`
31
+ - premise-driven schema selection via factual order context
32
+
33
+ ## What changes
34
+
35
+ Without matching authoritative state, no workflow is selected.
36
+
37
+ With policy state:
38
+
39
+ ```text
40
+ use refund_intake
41
+ ```
42
+
43
+ the refund workflow runs.
44
+
45
+ With a factual premise:
46
+
47
+ ```text
48
+ set premise order A-100 is a delivered physical item reported as damaged on arrival
49
+ ```
50
+
51
+ the same ambiguous user request, `I need help with order A-100.`, selects the
52
+ `refund_intake` schema.
53
+
54
+ The host maps that saved premise to the `damaged_physical_delivery` intake
55
+ category, which then maps to `refund_intake`.
56
+
57
+ With a different factual premise:
58
+
59
+ ```text
60
+ set premise order A-100 is a digital subscription with an active login failure after purchase
61
+ ```
62
+
63
+ the same ambiguous user request selects the `technical_support` schema.
64
+
65
+ The host maps that saved premise to the
66
+ `digital_subscription_login_failure` intake category, which then maps to
67
+ `technical_support`.
68
+
69
+ The premise is factual context about the order. It is not a workflow command
70
+ and it is not rewritten as `use refund_intake` or `use technical_support`.
71
+ This mapping is host-owned business logic, not model inference.
72
+
73
+ ## Proof
74
+
75
+ The tests verify:
76
+
77
+ ```python
78
+ assert refund_handler.called is True
79
+ assert technical_support_handler.called is False
80
+ ```
81
+
82
+ They also verify:
83
+
84
+ - `use refund_intake` selects `refund_intake`
85
+ - `use technical_support` selects `technical_support`
86
+ - saved premise facts map to a named intake category before schema selection
87
+ - the same request plus different saved premise selects different schemas
88
+ - unrelated premise selects no schema
89
+ - adversarial user text does not override saved policy or saved premise
90
+
91
+ ## Test
92
+
93
+ ```shell
94
+ uv run pytest python/tests/test_refund_intake_example.py
95
+ ```
@@ -0,0 +1 @@
1
+ """Refund intake schema-selection example."""
@@ -0,0 +1,180 @@
1
+ """Minimal host-side schema selection for refund intake."""
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Literal, TypedDict
5
+
6
+ from context_compiler import (
7
+ POLICY_USE,
8
+ State,
9
+ create_engine,
10
+ get_policy_items,
11
+ get_premise_value,
12
+ )
13
+
14
+ DAMAGED_ORDER_PREMISE = (
15
+ "order A-100 is a delivered physical item reported as damaged on arrival"
16
+ )
17
+ DIGITAL_LOGIN_FAILURE_PREMISE = (
18
+ "order A-100 is a digital subscription with an active login failure after purchase"
19
+ )
20
+
21
+
22
+ class IntakeRequest(TypedDict):
23
+ customer_id: str
24
+ message: str
25
+
26
+
27
+ class RefundIntakeResult(TypedDict):
28
+ kind: Literal["refund"]
29
+ customer_id: str
30
+ reason: str
31
+
32
+
33
+ class TechnicalSupportResult(TypedDict):
34
+ kind: Literal["technical_support"]
35
+ customer_id: str
36
+ issue: str
37
+
38
+
39
+ OrderIntakeContext = Literal[
40
+ "damaged_physical_delivery", "digital_subscription_login_failure"
41
+ ]
42
+
43
+
44
+ class IntakeRunResult(TypedDict):
45
+ selected_schema: str | None
46
+ refund_handler_called: bool
47
+ technical_support_handler_called: bool
48
+ result: RefundIntakeResult | TechnicalSupportResult | None
49
+
50
+
51
+ _SCHEMA_BY_ORDER_INTAKE_CONTEXT: dict[OrderIntakeContext, str] = {
52
+ "damaged_physical_delivery": "refund_intake",
53
+ "digital_subscription_login_failure": "technical_support",
54
+ }
55
+
56
+
57
+ @dataclass
58
+ class IntakeHandler:
59
+ name: str
60
+ called: bool = False
61
+
62
+ def handle(
63
+ self, request: IntakeRequest
64
+ ) -> RefundIntakeResult | TechnicalSupportResult:
65
+ self.called = True
66
+
67
+ if self.name == "refund_intake":
68
+ return {
69
+ "kind": "refund",
70
+ "customer_id": request["customer_id"],
71
+ "reason": request["message"],
72
+ }
73
+
74
+ if self.name == "technical_support":
75
+ return {
76
+ "kind": "technical_support",
77
+ "customer_id": request["customer_id"],
78
+ "issue": request["message"],
79
+ }
80
+
81
+ raise ValueError(f"unknown handler: {self.name}")
82
+
83
+
84
+ def classify_premise_as_order_intake_context(
85
+ premise: str | None,
86
+ ) -> OrderIntakeContext | None:
87
+ """Map saved order facts to a host-owned intake context."""
88
+
89
+ if premise is None:
90
+ return None
91
+
92
+ normalized_premise = premise.casefold()
93
+ if (
94
+ "delivered physical item" in normalized_premise
95
+ and "damaged on arrival" in normalized_premise
96
+ ):
97
+ return "damaged_physical_delivery"
98
+
99
+ if (
100
+ "digital subscription" in normalized_premise
101
+ and "login failure" in normalized_premise
102
+ ):
103
+ return "digital_subscription_login_failure"
104
+
105
+ return None
106
+
107
+
108
+ def select_schema_from_order_intake_context(
109
+ context: OrderIntakeContext | None,
110
+ ) -> str | None:
111
+ """Map a host-owned intake context to the selected schema."""
112
+
113
+ if context is None:
114
+ return None
115
+
116
+ return _SCHEMA_BY_ORDER_INTAKE_CONTEXT[context]
117
+
118
+
119
+ def select_schema_from_state(state: State) -> str | None:
120
+ """Select a host-side workflow from authoritative state."""
121
+
122
+ use_items = set(get_policy_items(state, POLICY_USE))
123
+ premise = get_premise_value(state)
124
+
125
+ if "refund_intake" in use_items:
126
+ return "refund_intake"
127
+
128
+ if "technical_support" in use_items:
129
+ return "technical_support"
130
+
131
+ intake_context = classify_premise_as_order_intake_context(premise)
132
+ return select_schema_from_order_intake_context(intake_context)
133
+
134
+
135
+ def run_intake(
136
+ request: IntakeRequest,
137
+ *,
138
+ selected_schema: str | None,
139
+ refund_handler: IntakeHandler,
140
+ technical_support_handler: IntakeHandler,
141
+ ) -> RefundIntakeResult | TechnicalSupportResult | None:
142
+ """Dispatch to the selected host-side handler, if any."""
143
+
144
+ if selected_schema == "refund_intake":
145
+ return refund_handler.handle(request)
146
+
147
+ if selected_schema == "technical_support":
148
+ return technical_support_handler.handle(request)
149
+
150
+ return None
151
+
152
+
153
+ def run_demo() -> IntakeRunResult:
154
+ """Run a small demonstration with refund_intake enabled."""
155
+
156
+ engine = create_engine()
157
+ engine.step("use refund_intake")
158
+
159
+ request: IntakeRequest = {
160
+ "customer_id": "customer-123",
161
+ "message": "I need a refund for order A-100.",
162
+ }
163
+
164
+ refund_handler = IntakeHandler("refund_intake")
165
+ technical_support_handler = IntakeHandler("technical_support")
166
+
167
+ selected_schema = select_schema_from_state(engine.state)
168
+ result = run_intake(
169
+ request,
170
+ selected_schema=selected_schema,
171
+ refund_handler=refund_handler,
172
+ technical_support_handler=technical_support_handler,
173
+ )
174
+
175
+ return {
176
+ "selected_schema": selected_schema,
177
+ "refund_handler_called": refund_handler.called,
178
+ "technical_support_handler_called": technical_support_handler.called,
179
+ "result": result,
180
+ }
@@ -0,0 +1,55 @@
1
+ # Tool gating
2
+
3
+ These examples show the host deciding which tools exist at runtime and which
4
+ tool calls can execute.
5
+
6
+ Context Compiler owns the authoritative policy state.
7
+
8
+ The host owns the tool registry and tool execution.
9
+
10
+ Adversarial wording does not expose hidden tools or authorize blocked tools.
11
+
12
+ ## Examples
13
+
14
+ ### `calendar_admin`
15
+
16
+ Exposes a host-owned `calendar_admin_create_event` tool only when state
17
+ contains:
18
+
19
+ ```text
20
+ use calendar_admin
21
+ ```
22
+
23
+ The host hides and blocks the tool when state is absent or when state contains:
24
+
25
+ ```text
26
+ prohibit calendar_admin
27
+ ```
28
+
29
+ The tests cover visible-tool changes, execution blocking, adversarial text, and
30
+ contradiction / clarification behavior.
31
+
32
+ ### `mcp_calendar_admin`
33
+
34
+ Uses MCP as the integration surface while keeping Context Compiler as the
35
+ authority source.
36
+
37
+ The host exposes the `calendar_admin_create_event` MCP tool only when state
38
+ contains:
39
+
40
+ ```text
41
+ use calendar_admin
42
+ ```
43
+
44
+ When state is absent or contains:
45
+
46
+ ```text
47
+ prohibit calendar_admin
48
+ ```
49
+
50
+ the MCP tool is absent from the exposed tool set and blocked if invoked
51
+ directly.
52
+
53
+ This example also includes an opt-in live-model comparison showing that a real
54
+ tool-calling model can only act through the MCP tool surface the host exposes
55
+ from authoritative Context Compiler state.
@@ -0,0 +1,34 @@
1
+ # `calendar_admin`
2
+
3
+ This example shows host-side tool gating with explicit authoritative Context
4
+ Compiler state.
5
+
6
+ The host owns the tool registry and tool execution.
7
+
8
+ Context Compiler owns the policy state that decides whether the host exposes
9
+ `calendar_admin_create_event`.
10
+
11
+ The host exposes and allows the calendar admin tool only when state contains:
12
+
13
+ ```text
14
+ use calendar_admin
15
+ ```
16
+
17
+ The host hides and blocks the calendar admin tool when state is absent or when
18
+ state contains:
19
+
20
+ ```text
21
+ prohibit calendar_admin
22
+ ```
23
+
24
+ Adversarial request text does not enable the tool because the host never derives
25
+ authority from user wording or model output.
26
+
27
+ The tests cover:
28
+
29
+ - allowed exposure and execution
30
+ - absent-state hiding and blocking
31
+ - prohibited-state hiding and blocking
32
+ - adversarial text that tries to self-authorize
33
+ - runtime behavior changing only when authoritative state changes
34
+ - contradiction and clarification behavior for conflicting `use` and `prohibit`
@@ -0,0 +1 @@
1
+ """Calendar admin tool-gating example."""