From 8fb74f83f3f52459a0288efc8147a136dd405703 Mon Sep 17 00:00:00 2001 From: Ken Chau Date: Mon, 4 May 2026 14:18:02 -0700 Subject: [PATCH 01/11] feat(core): add cost_usd: Decimal | None to Usage model Declared field (not extras bag) so Pydantic enforces the type. Float input is rejected with an explicit error message. None = unknown cost, Decimal('0') = explicitly free. Serializes as string in JSON mode for safe transport. --- bindings/python/tests/test_cost_models.py | 103 ++++++++++++++++++++++ python/amplifier_core/message_models.py | 14 +++ 2 files changed, 117 insertions(+) create mode 100644 bindings/python/tests/test_cost_models.py diff --git a/bindings/python/tests/test_cost_models.py b/bindings/python/tests/test_cost_models.py new file mode 100644 index 00000000..f748f590 --- /dev/null +++ b/bindings/python/tests/test_cost_models.py @@ -0,0 +1,103 @@ +"""Tests for cost_usd fields on Usage and SessionStatus. + +Verifies: +- cost_usd is a declared Decimal field (not bag extra) +- Pydantic validates Decimal type — rejects float +- None means unknown (not zero) +- Decimal("0") means explicitly free +- SessionStatus.estimated_cost is removed (was never populated) +""" + +from decimal import Decimal, InvalidOperation # noqa: F401 — used in Task 2 (TestSessionStatusCostUsd) + +import pytest +from pydantic import ValidationError + +from amplifier_core.message_models import Usage +from amplifier_core.models import SessionStatus # noqa: F401 — used in Task 2 (TestSessionStatusCostUsd) + + +class TestUsageCostUsd: + def test_cost_usd_defaults_to_none(self): + """cost_usd is None when not provided — all existing Usage construction is unaffected.""" + usage = Usage(input_tokens=100, output_tokens=50, total_tokens=150) + assert usage.cost_usd is None + + def test_cost_usd_accepts_decimal(self): + """cost_usd should accept a Decimal value.""" + usage = Usage( + input_tokens=100, + output_tokens=50, + total_tokens=150, + cost_usd=Decimal("0.047832"), + ) + assert usage.cost_usd == Decimal("0.047832") + assert isinstance(usage.cost_usd, Decimal) + + def test_cost_usd_accepts_decimal_zero(self): + """Decimal('0') is valid — means explicitly free (not unknown).""" + usage = Usage( + input_tokens=0, output_tokens=0, total_tokens=0, cost_usd=Decimal("0") + ) + assert usage.cost_usd == Decimal("0") + assert usage.cost_usd is not None # None != 0 + + def test_cost_usd_rejects_float(self): + """Float must be rejected — Pydantic should raise ValidationError for float input.""" + with pytest.raises((ValidationError, TypeError)): + Usage( + input_tokens=100, + output_tokens=50, + total_tokens=150, + cost_usd=0.047, # float — not acceptable for monetary values + ) + + def test_cost_usd_accepts_decimal_from_string(self): + """Decimal coercion from string is acceptable (event dict transport pattern).""" + usage = Usage( + input_tokens=100, + output_tokens=50, + total_tokens=150, + cost_usd=Decimal("0.0478"), + ) + assert usage.cost_usd == Decimal("0.0478") + + def test_none_is_not_zero(self): + """Explicit contract: None (unknown) != Decimal('0') (free).""" + unknown = Usage(input_tokens=1, output_tokens=1, total_tokens=2) + free = Usage( + input_tokens=0, output_tokens=0, total_tokens=0, cost_usd=Decimal("0") + ) + assert unknown.cost_usd is None + assert free.cost_usd == Decimal("0") + assert unknown.cost_usd != free.cost_usd + + def test_model_dump_includes_cost_usd_as_decimal(self): + """model_dump() should include cost_usd as Decimal (not string, not float).""" + usage = Usage( + input_tokens=100, + output_tokens=50, + total_tokens=150, + cost_usd=Decimal("0.047"), + ) + dumped = usage.model_dump() + assert "cost_usd" in dumped + assert isinstance(dumped["cost_usd"], Decimal) + + def test_model_dump_json_mode_serializes_cost_usd_as_string(self): + """model_dump(mode='json') serializes Decimal as string for JSON safety.""" + usage = Usage( + input_tokens=100, + output_tokens=50, + total_tokens=150, + cost_usd=Decimal("0.047"), + ) + dumped = usage.model_dump(mode="json") + assert isinstance(dumped["cost_usd"], str) + assert dumped["cost_usd"] == "0.047" + + def test_cost_usd_not_in_dump_when_none(self): + """When cost_usd is None, model_dump(exclude_none=True) omits it.""" + usage = Usage(input_tokens=100, output_tokens=50, total_tokens=150) + dumped = usage.model_dump(exclude_none=True) + assert "cost_usd" not in dumped diff --git a/python/amplifier_core/message_models.py b/python/amplifier_core/message_models.py index 359312aa..dd86c3fc 100644 --- a/python/amplifier_core/message_models.py +++ b/python/amplifier_core/message_models.py @@ -14,6 +14,8 @@ - docs/schemas/request_envelope_v1.json for JSON schema """ +from decimal import Decimal + from typing import Annotated from typing import Any from typing import Literal @@ -22,6 +24,7 @@ from pydantic import BaseModel from pydantic import ConfigDict from pydantic import Field +from pydantic import field_validator class TextBlock(BaseModel): @@ -242,6 +245,17 @@ class Usage(BaseModel): reasoning_tokens: int | None = None cache_read_tokens: int | None = None cache_write_tokens: int | None = None + cost_usd: Decimal | None = None + + @field_validator("cost_usd", mode="before") + @classmethod + def reject_float_cost(cls, v): + if isinstance(v, float): + raise ValueError( + "cost_usd must be Decimal, not float. " + "Use Decimal('0.047') — floats lose monetary precision." + ) + return v class Degradation(BaseModel): From baed1094d9fdeeed8290607e8e2a316a4113295e Mon Sep 17 00:00:00 2001 From: Ken Chau Date: Mon, 4 May 2026 14:25:41 -0700 Subject: [PATCH 02/11] =?UTF-8?q?test(core):=20tighten=20TestUsageCostUsd?= =?UTF-8?q?=20=E2=80=94=20remove=20speculative=20imports,=20fix=20string?= =?UTF-8?q?=20test,=20narrow=20exception?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bindings/python/tests/test_cost_models.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/bindings/python/tests/test_cost_models.py b/bindings/python/tests/test_cost_models.py index f748f590..489ee978 100644 --- a/bindings/python/tests/test_cost_models.py +++ b/bindings/python/tests/test_cost_models.py @@ -8,13 +8,12 @@ - SessionStatus.estimated_cost is removed (was never populated) """ -from decimal import Decimal, InvalidOperation # noqa: F401 — used in Task 2 (TestSessionStatusCostUsd) +from decimal import Decimal import pytest from pydantic import ValidationError from amplifier_core.message_models import Usage -from amplifier_core.models import SessionStatus # noqa: F401 — used in Task 2 (TestSessionStatusCostUsd) class TestUsageCostUsd: @@ -44,7 +43,7 @@ def test_cost_usd_accepts_decimal_zero(self): def test_cost_usd_rejects_float(self): """Float must be rejected — Pydantic should raise ValidationError for float input.""" - with pytest.raises((ValidationError, TypeError)): + with pytest.raises(ValidationError): Usage( input_tokens=100, output_tokens=50, @@ -55,12 +54,11 @@ def test_cost_usd_rejects_float(self): def test_cost_usd_accepts_decimal_from_string(self): """Decimal coercion from string is acceptable (event dict transport pattern).""" usage = Usage( - input_tokens=100, - output_tokens=50, - total_tokens=150, - cost_usd=Decimal("0.0478"), + input_tokens=100, output_tokens=50, total_tokens=150, + cost_usd="0.0478", # raw string, as it would arrive from a JSON dict ) assert usage.cost_usd == Decimal("0.0478") + assert isinstance(usage.cost_usd, Decimal) def test_none_is_not_zero(self): """Explicit contract: None (unknown) != Decimal('0') (free).""" From d46a63a1d919091e0198203deffa0d7734598228 Mon Sep 17 00:00:00 2001 From: Ken Chau Date: Mon, 4 May 2026 14:30:24 -0700 Subject: [PATCH 03/11] feat(core): add cost_usd: Decimal to SessionStatus; deprecate estimated_cost: float cost_usd is the canonical accumulated session cost. estimated_cost kept with deprecated=True for backward compat. Float input rejected with explicit validation error. --- bindings/python/tests/test_cost_models.py | 33 ++++++++++++++++++++++- python/amplifier_core/models.py | 28 +++++++++++++++++-- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/bindings/python/tests/test_cost_models.py b/bindings/python/tests/test_cost_models.py index 489ee978..bfc8ab1a 100644 --- a/bindings/python/tests/test_cost_models.py +++ b/bindings/python/tests/test_cost_models.py @@ -14,6 +14,7 @@ from pydantic import ValidationError from amplifier_core.message_models import Usage +from amplifier_core.models import SessionStatus class TestUsageCostUsd: @@ -54,7 +55,9 @@ def test_cost_usd_rejects_float(self): def test_cost_usd_accepts_decimal_from_string(self): """Decimal coercion from string is acceptable (event dict transport pattern).""" usage = Usage( - input_tokens=100, output_tokens=50, total_tokens=150, + input_tokens=100, + output_tokens=50, + total_tokens=150, cost_usd="0.0478", # raw string, as it would arrive from a JSON dict ) assert usage.cost_usd == Decimal("0.0478") @@ -99,3 +102,31 @@ def test_cost_usd_not_in_dump_when_none(self): usage = Usage(input_tokens=100, output_tokens=50, total_tokens=150) dumped = usage.model_dump(exclude_none=True) assert "cost_usd" not in dumped + + +class TestSessionStatusCostUsd: + def test_cost_usd_defaults_to_none(self): + status = SessionStatus(session_id="test-123") + assert status.cost_usd is None + + def test_cost_usd_accepts_decimal(self): + status = SessionStatus(session_id="test-123", cost_usd=Decimal("1.234567")) + assert status.cost_usd == Decimal("1.234567") + assert isinstance(status.cost_usd, Decimal) + + def test_cost_usd_rejects_float(self): + with pytest.raises(ValidationError): + SessionStatus(session_id="test-123", cost_usd=1.23) + + def test_estimated_cost_deprecated_but_still_works(self): + """estimated_cost still accepts float for backward compat (deprecated, not removed).""" + status = SessionStatus(session_id="test-123", estimated_cost=0.5) + assert status.estimated_cost == 0.5 + + def test_to_dict_includes_cost_usd_as_string(self): + """to_dict() uses mode='json' — cost_usd should serialize as string.""" + status = SessionStatus(session_id="test-123", cost_usd=Decimal("2.50")) + d = status.to_dict() + assert "cost_usd" in d + assert isinstance(d["cost_usd"], str) + assert d["cost_usd"] == "2.50" diff --git a/python/amplifier_core/models.py b/python/amplifier_core/models.py index 92c4e7bc..e8540386 100644 --- a/python/amplifier_core/models.py +++ b/python/amplifier_core/models.py @@ -6,11 +6,13 @@ import json import re from datetime import datetime +from decimal import Decimal from typing import Any from typing import Literal from pydantic import BaseModel from pydantic import Field +from pydantic import field_validator def _sanitize_for_llm(text: str) -> str: @@ -417,8 +419,30 @@ class SessionStatus(BaseModel): total_input_tokens: int = 0 total_output_tokens: int = 0 - # Cost tracking (if available) - estimated_cost: float | None = None + # Cost tracking + cost_usd: Decimal | None = Field( + default=None, + description=( + "Accumulated session cost in USD. " + "None = rate data unavailable (not zero). " + "Populated by provider session contributors." + ), + ) + estimated_cost: float | None = Field( + default=None, + deprecated=True, + description="Deprecated: use cost_usd (Decimal). Will be removed in a future release.", + ) + + @field_validator("cost_usd", mode="before") + @classmethod + def reject_float_cost_usd(cls, v): + if isinstance(v, float): + raise ValueError( + "cost_usd must be Decimal, not float. " + "Use Decimal('1.23') — floats lose monetary precision." + ) + return v # Last activity last_activity: datetime | None = None From b7a888077ec0dd7403a668ab45e24052888ca6ea Mon Sep 17 00:00:00 2001 From: Ken Chau Date: Mon, 4 May 2026 14:41:08 -0700 Subject: [PATCH 04/11] feat(core): add cost_usd: Option to Rust SessionStatus String type matches Decimal's JSON serialization convention. estimated_cost: Option retained for backward compat. Also adds TestSchemaSync Python tests verifying that the Pydantic model schema includes cost_usd with string-compatible type. --- bindings/python/tests/test_cost_models.py | 16 ++++++++++++++++ crates/amplifier-core/src/models.rs | 23 +++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/bindings/python/tests/test_cost_models.py b/bindings/python/tests/test_cost_models.py index bfc8ab1a..1db25357 100644 --- a/bindings/python/tests/test_cost_models.py +++ b/bindings/python/tests/test_cost_models.py @@ -130,3 +130,19 @@ def test_to_dict_includes_cost_usd_as_string(self): assert "cost_usd" in d assert isinstance(d["cost_usd"], str) assert d["cost_usd"] == "2.50" + +class TestSchemaSync: + def test_session_status_schema_has_cost_usd(self): + """JSON schema for SessionStatus must include cost_usd.""" + schema = SessionStatus.model_json_schema() + props = schema.get("properties", {}) + assert "cost_usd" in props, f"cost_usd missing. Keys: {list(props.keys())}" + + def test_session_status_schema_cost_usd_is_string_type(self): + """In JSON schema, cost_usd should be string (Decimal serializes as string).""" + schema = SessionStatus.model_json_schema() + cost_prop = schema["properties"]["cost_usd"] + types = [t.get("type") for t in cost_prop.get("anyOf", [cost_prop])] + assert "string" in types or cost_prop.get("type") == "string", ( + f"cost_usd schema type should include 'string', got: {cost_prop}" + ) diff --git a/crates/amplifier-core/src/models.rs b/crates/amplifier-core/src/models.rs index b18b5764..03474d60 100644 --- a/crates/amplifier-core/src/models.rs +++ b/crates/amplifier-core/src/models.rs @@ -451,7 +451,12 @@ pub struct SessionStatus { pub total_output_tokens: i64, // Cost tracking - /// Estimated cost (if available). + /// Accumulated session cost in USD as a decimal string (e.g., "0.047832"). + /// None means rate data was unavailable — not zero cost. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub cost_usd: Option, + + /// Deprecated: use cost_usd. Retained for backward compatibility. #[serde(default)] pub estimated_cost: Option, @@ -866,6 +871,7 @@ mod tests { tool_failures: 1, total_input_tokens: 1000, total_output_tokens: 500, + cost_usd: None, estimated_cost: Some(0.05), last_activity: Some("2025-01-01T00:01:00Z".into()), last_error: None, @@ -887,4 +893,17 @@ mod tests { assert_eq!(status.tool_invocations, 0); assert!(status.ended_at.is_none()); } -} + #[test] + fn session_status_cost_usd_roundtrip() { + // Verifies cost_usd: Option is present and roundtrips correctly. + // String type matches Decimal JSON serialization on the Python side. + let json = r#"{"session_id": "s1", "started_at": "2025-01-01T00:00:00Z", "cost_usd": "0.047832"}"#; + let status: SessionStatus = serde_json::from_str(json).unwrap(); + assert_eq!(status.cost_usd, Some("0.047832".to_string())); + + // None when absent (unknown cost, not zero) + let json_no_cost = r#"{"session_id": "s2", "started_at": "2025-01-01T00:00:00Z"}"#; + let status_no_cost: SessionStatus = serde_json::from_str(json_no_cost).unwrap(); + assert!(status_no_cost.cost_usd.is_none()); + } +} \ No newline at end of file From 33fe131aa29f103af352be2eb7573c8ac55de789 Mon Sep 17 00:00:00 2001 From: Ken Chau Date: Mon, 4 May 2026 14:43:28 -0700 Subject: [PATCH 05/11] feat(core): add cost_usd: optional string to proto Usage message Field 7. String matches Decimal JSON serialization. None = unknown cost. Proto stubs regenerated with grpc_tools.protoc. --- proto/amplifier_module.proto | 1 + proto/amplifier_module_pb2.py | 216 +++++++++++++-------------- proto/test_task03_module_specific.py | 21 +++ 3 files changed, 130 insertions(+), 108 deletions(-) diff --git a/proto/amplifier_module.proto b/proto/amplifier_module.proto index e12f988a..ca65a007 100644 --- a/proto/amplifier_module.proto +++ b/proto/amplifier_module.proto @@ -305,6 +305,7 @@ message Usage { optional int32 reasoning_tokens = 4; optional int32 cache_read_tokens = 5; optional int32 cache_creation_tokens = 6; + optional string cost_usd = 7; // Decimal as string; None = unknown cost } message Degradation { diff --git a/proto/amplifier_module_pb2.py b/proto/amplifier_module_pb2.py index 6f4d7515..c43ce6a0 100644 --- a/proto/amplifier_module_pb2.py +++ b/proto/amplifier_module_pb2.py @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x61mplifier_module.proto\x12\x10\x61mplifier.module\"\x07\n\x05\x45mpty\"F\n\x08ToolSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x17\n\x0fparameters_json\x18\x03 \x01(\t\"9\n\x12ToolExecuteRequest\x12\r\n\x05input\x18\x01 \x01(\x0c\x12\x14\n\x0c\x63ontent_type\x18\x02 \x01(\t\"[\n\x13ToolExecuteResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0e\n\x06output\x18\x02 \x01(\x0c\x12\x14\n\x0c\x63ontent_type\x18\x03 \x01(\t\x12\r\n\x05\x65rror\x18\x04 \x01(\t\"\xd6\x01\n\nModuleInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t\x12\x31\n\x0bmodule_type\x18\x04 \x01(\x0e\x32\x1c.amplifier.module.ModuleType\x12\x13\n\x0bmount_point\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t\x12\x1a\n\x12\x63onfig_schema_json\x18\x07 \x01(\t\x12\x14\n\x0c\x63\x61pabilities\x18\x08 \x03(\t\x12\x0e\n\x06\x61uthor\x18\t \x01(\t\"\x8c\x01\n\x0cMountRequest\x12:\n\x06\x63onfig\x18\x01 \x03(\x0b\x32*.amplifier.module.MountRequest.ConfigEntry\x12\x11\n\tmodule_id\x18\x02 \x01(\t\x1a-\n\x0b\x43onfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"_\n\rMountResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12.\n\x06status\x18\x03 \x01(\x0e\x32\x1e.amplifier.module.HealthStatus\"V\n\x13HealthCheckResponse\x12.\n\x06status\x18\x01 \x01(\x0e\x32\x1e.amplifier.module.HealthStatus\x12\x0f\n\x07message\x18\x02 \x01(\t\"\xca\x02\n\x0b\x43onfigField\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x35\n\nfield_type\x18\x03 \x01(\x0e\x32!.amplifier.module.ConfigFieldType\x12\x0e\n\x06prompt\x18\x04 \x01(\t\x12\x0f\n\x07\x65nv_var\x18\x05 \x01(\t\x12\x0f\n\x07\x63hoices\x18\x06 \x03(\t\x12\x10\n\x08required\x18\x07 \x01(\x08\x12\x15\n\rdefault_value\x18\x08 \x01(\t\x12>\n\tshow_when\x18\t \x03(\x0b\x32+.amplifier.module.ConfigField.ShowWhenEntry\x12\x16\n\x0erequires_model\x18\n \x01(\x08\x1a/\n\rShowWhenEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xbc\x01\n\rProviderError\x12\x37\n\nerror_type\x18\x01 \x01(\x0e\x32#.amplifier.module.ProviderErrorType\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x15\n\rprovider_name\x18\x03 \x01(\t\x12\r\n\x05model\x18\x04 \x01(\t\x12\x13\n\x0bstatus_code\x18\x05 \x01(\x05\x12\x11\n\tretryable\x18\x06 \x01(\x08\x12\x13\n\x0bretry_after\x18\x07 \x01(\x01\"\x97\x01\n\tToolError\x12\x33\n\nerror_type\x18\x01 \x01(\x0e\x32\x1f.amplifier.module.ToolErrorType\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x11\n\ttool_name\x18\x03 \x01(\t\x12\x0e\n\x06stdout\x18\x04 \x01(\t\x12\x0e\n\x06stderr\x18\x05 \x01(\t\x12\x11\n\texit_code\x18\x06 \x01(\x05\"d\n\tHookError\x12\x33\n\nerror_type\x18\x01 \x01(\x0e\x32\x1f.amplifier.module.HookErrorType\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x11\n\thook_name\x18\x03 \x01(\t\"\xef\x01\n\x0e\x41mplifierError\x12\x39\n\x0eprovider_error\x18\x01 \x01(\x0b\x32\x1f.amplifier.module.ProviderErrorH\x00\x12\x31\n\ntool_error\x18\x02 \x01(\x0b\x32\x1b.amplifier.module.ToolErrorH\x00\x12\x31\n\nhook_error\x18\x03 \x01(\x0b\x32\x1b.amplifier.module.HookErrorH\x00\x12\x17\n\rgeneric_error\x18\x04 \x01(\tH\x00\x12\x1a\n\x10validation_error\x18\x05 \x01(\tH\x00\x42\x07\n\x05\x65rror\"\x19\n\tTextBlock\x12\x0c\n\x04text\x18\x01 \x01(\t\"E\n\rThinkingBlock\x12\x10\n\x08thinking\x18\x01 \x01(\t\x12\x11\n\tsignature\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\"%\n\x15RedactedThinkingBlock\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\t\"=\n\rToolCallBlock\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x12\n\ninput_json\x18\x03 \x01(\t\"<\n\x0fToolResultBlock\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x13\n\x0boutput_json\x18\x02 \x01(\t\"C\n\nImageBlock\x12\x12\n\nmedia_type\x18\x01 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\x13\n\x0bsource_json\x18\x03 \x01(\t\"2\n\x0eReasoningBlock\x12\x0f\n\x07\x63ontent\x18\x01 \x03(\t\x12\x0f\n\x07summary\x18\x02 \x03(\t\"\xf1\x03\n\x0c\x43ontentBlock\x12\x31\n\ntext_block\x18\x01 \x01(\x0b\x32\x1b.amplifier.module.TextBlockH\x00\x12\x39\n\x0ethinking_block\x18\x02 \x01(\x0b\x32\x1f.amplifier.module.ThinkingBlockH\x00\x12J\n\x17redacted_thinking_block\x18\x03 \x01(\x0b\x32\'.amplifier.module.RedactedThinkingBlockH\x00\x12:\n\x0ftool_call_block\x18\x04 \x01(\x0b\x32\x1f.amplifier.module.ToolCallBlockH\x00\x12>\n\x11tool_result_block\x18\x05 \x01(\x0b\x32!.amplifier.module.ToolResultBlockH\x00\x12\x33\n\x0bimage_block\x18\x06 \x01(\x0b\x32\x1c.amplifier.module.ImageBlockH\x00\x12;\n\x0freasoning_block\x18\x07 \x01(\x0b\x32 .amplifier.module.ReasoningBlockH\x00\x12\x30\n\nvisibility\x18\x08 \x01(\x0e\x32\x1c.amplifier.module.VisibilityB\x07\n\x05\x62lock\"B\n\x10\x43ontentBlockList\x12.\n\x06\x62locks\x18\x01 \x03(\x0b\x32\x1e.amplifier.module.ContentBlock\"\xca\x01\n\x07Message\x12$\n\x04role\x18\x01 \x01(\x0e\x32\x16.amplifier.module.Role\x12\x16\n\x0ctext_content\x18\x02 \x01(\tH\x00\x12;\n\rblock_content\x18\x03 \x01(\x0b\x32\".amplifier.module.ContentBlockListH\x00\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x14\n\x0ctool_call_id\x18\x05 \x01(\t\x12\x15\n\rmetadata_json\x18\x06 \x01(\tB\t\n\x07\x63ontent\"C\n\x0fToolCallMessage\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"K\n\rToolSpecProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x17\n\x0fparameters_json\x18\x03 \x01(\t\"7\n\x10JsonSchemaFormat\x12\x13\n\x0bschema_json\x18\x01 \x01(\t\x12\x0e\n\x06strict\x18\x02 \x01(\x08\"u\n\x0eResponseFormat\x12\x0e\n\x04text\x18\x01 \x01(\x08H\x00\x12\x0e\n\x04json\x18\x02 \x01(\x08H\x00\x12\x39\n\x0bjson_schema\x18\x03 \x01(\x0b\x32\".amplifier.module.JsonSchemaFormatH\x00\x42\x08\n\x06\x66ormat\"\xf7\x01\n\x05Usage\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\x12\x1d\n\x10reasoning_tokens\x18\x04 \x01(\x05H\x00\x88\x01\x01\x12\x1e\n\x11\x63\x61\x63he_read_tokens\x18\x05 \x01(\x05H\x01\x88\x01\x01\x12\"\n\x15\x63\x61\x63he_creation_tokens\x18\x06 \x01(\x05H\x02\x88\x01\x01\x42\x13\n\x11_reasoning_tokensB\x14\n\x12_cache_read_tokensB\x18\n\x16_cache_creation_tokens\"@\n\x0b\x44\x65gradation\x12\x11\n\trequested\x18\x01 \x01(\t\x12\x0e\n\x06\x61\x63tual\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\"\x81\x03\n\x0b\x43hatRequest\x12+\n\x08messages\x18\x01 \x03(\x0b\x32\x19.amplifier.module.Message\x12.\n\x05tools\x18\x02 \x03(\x0b\x32\x1f.amplifier.module.ToolSpecProto\x12\x39\n\x0fresponse_format\x18\x03 \x01(\x0b\x32 .amplifier.module.ResponseFormat\x12\x13\n\x0btemperature\x18\x04 \x01(\x01\x12\r\n\x05top_p\x18\x05 \x01(\x01\x12\x19\n\x11max_output_tokens\x18\x06 \x01(\x05\x12\x17\n\x0f\x63onversation_id\x18\x07 \x01(\t\x12\x0e\n\x06stream\x18\x08 \x01(\x08\x12\x15\n\rmetadata_json\x18\t \x01(\t\x12\r\n\x05model\x18\n \x01(\t\x12\x13\n\x0btool_choice\x18\x0b \x01(\t\x12\x0c\n\x04stop\x18\x0c \x03(\t\x12\x18\n\x10reasoning_effort\x18\r \x01(\t\x12\x0f\n\x07timeout\x18\x0e \x01(\x01\"\x98\x02\n\x0c\x43hatResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x35\n\ntool_calls\x18\x02 \x03(\x0b\x32!.amplifier.module.ToolCallMessage\x12&\n\x05usage\x18\x03 \x01(\x0b\x32\x17.amplifier.module.Usage\x12\x32\n\x0b\x64\x65gradation\x18\x04 \x01(\x0b\x32\x1d.amplifier.module.Degradation\x12\x15\n\rfinish_reason\x18\x05 \x01(\t\x12\x15\n\rmetadata_json\x18\x06 \x01(\t\x12\x36\n\x0e\x63ontent_blocks\x18\x07 \x03(\x0b\x32\x1e.amplifier.module.ContentBlock\"F\n\nToolResult\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x13\n\x0boutput_json\x18\x02 \x01(\t\x12\x12\n\nerror_json\x18\x03 \x01(\t\"\xa7\x04\n\nHookResult\x12,\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\x1c.amplifier.module.HookAction\x12\x11\n\tdata_json\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x19\n\x11\x63ontext_injection\x18\x04 \x01(\t\x12\x46\n\x16\x63ontext_injection_role\x18\x05 \x01(\x0e\x32&.amplifier.module.ContextInjectionRole\x12\x11\n\tephemeral\x18\x06 \x01(\x08\x12\x17\n\x0f\x61pproval_prompt\x18\x07 \x01(\t\x12\x18\n\x10\x61pproval_options\x18\x08 \x03(\t\x12\x1d\n\x10\x61pproval_timeout\x18\t \x01(\x01H\x00\x88\x01\x01\x12;\n\x10\x61pproval_default\x18\n \x01(\x0e\x32!.amplifier.module.ApprovalDefault\x12\x17\n\x0fsuppress_output\x18\x0b \x01(\x08\x12\x14\n\x0cuser_message\x18\x0c \x01(\t\x12>\n\x12user_message_level\x18\r \x01(\x0e\x32\".amplifier.module.UserMessageLevel\x12\x1b\n\x13user_message_source\x18\x0e \x01(\t\x12\"\n\x1a\x61ppend_to_last_tool_result\x18\x0f \x01(\x08\x42\x13\n\x11_approval_timeout\"\x8d\x01\n\tModelInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x16\n\x0e\x63ontext_window\x18\x03 \x01(\x05\x12\x19\n\x11max_output_tokens\x18\x04 \x01(\x05\x12\x14\n\x0c\x63\x61pabilities\x18\x05 \x03(\t\x12\x15\n\rdefaults_json\x18\x06 \x01(\t\"\xb0\x01\n\x0cProviderInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x1b\n\x13\x63redential_env_vars\x18\x03 \x03(\t\x12\x14\n\x0c\x63\x61pabilities\x18\x04 \x03(\t\x12\x15\n\rdefaults_json\x18\x05 \x01(\t\x12\x34\n\rconfig_fields\x18\x06 \x03(\x0b\x32\x1d.amplifier.module.ConfigField\"\x80\x01\n\x0f\x41pprovalRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x0e\n\x06\x61\x63tion\x18\x02 \x01(\t\x12\x14\n\x0c\x64\x65tails_json\x18\x03 \x01(\t\x12\x12\n\nrisk_level\x18\x04 \x01(\t\x12\x14\n\x07timeout\x18\x05 \x01(\x01H\x00\x88\x01\x01\x42\n\n\x08_timeout\"F\n\x10\x41pprovalResponse\x12\x10\n\x08\x61pproved\x18\x01 \x01(\x08\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x10\n\x08remember\x18\x03 \x01(\x08\"A\n\x12ListModelsResponse\x12+\n\x06models\x18\x01 \x03(\x0b\x32\x1b.amplifier.module.ModelInfo\"O\n\x16ParseToolCallsResponse\x12\x35\n\ntool_calls\x18\x01 \x03(\x0b\x32!.amplifier.module.ToolCallMessage\"@\n\x1aOrchestratorExecuteRequest\x12\x0e\n\x06prompt\x18\x01 \x01(\t\x12\x12\n\nsession_id\x18\x02 \x01(\t\">\n\x1bOrchestratorExecuteResponse\x12\x10\n\x08response\x18\x01 \x01(\t\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"?\n\x11\x41\x64\x64MessageRequest\x12*\n\x07message\x18\x01 \x01(\x0b\x32\x19.amplifier.module.Message\"B\n\x13GetMessagesResponse\x12+\n\x08messages\x18\x01 \x03(\x0b\x32\x19.amplifier.module.Message\"J\n\x1bGetMessagesForRequestParams\x12\x14\n\x0ctoken_budget\x18\x01 \x01(\x05\x12\x15\n\rprovider_name\x18\x02 \x01(\t\"A\n\x12SetMessagesRequest\x12+\n\x08messages\x18\x01 \x03(\x0b\x32\x19.amplifier.module.Message\"5\n\x11HookHandleRequest\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\tdata_json\x18\x02 \x01(\t\".\n\x17GetSubscriptionsRequest\x12\x13\n\x0b\x63onfig_json\x18\x01 \x01(\t\"V\n\x18GetSubscriptionsResponse\x12:\n\rsubscriptions\x18\x01 \x03(\x0b\x32#.amplifier.module.EventSubscription\"B\n\x11\x45ventSubscription\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x10\n\x08priority\x18\x02 \x01(\x05\x12\x0c\n\x04name\x18\x03 \x01(\t\"d\n\x1b\x43ompleteWithProviderRequest\x12\x15\n\rprovider_name\x18\x01 \x01(\t\x12.\n\x07request\x18\x02 \x01(\x0b\x32\x1d.amplifier.module.ChatRequest\";\n\x12\x45xecuteToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x12\n\ninput_json\x18\x02 \x01(\t\"3\n\x0f\x45mitHookRequest\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\tdata_json\x18\x02 \x01(\t\"V\n\x19\x45mitHookAndCollectRequest\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\tdata_json\x18\x02 \x01(\t\x12\x17\n\x0ftimeout_seconds\x18\x03 \x01(\x01\"4\n\x1a\x45mitHookAndCollectResponse\x12\x16\n\x0eresponses_json\x18\x01 \x03(\t\"(\n\x12GetMessagesRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"Y\n\x17KernelAddMessageRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12*\n\x07message\x18\x02 \x01(\x0b\x32\x19.amplifier.module.Message\"a\n\x17GetMountedModuleRequest\x12\x13\n\x0bmodule_name\x18\x01 \x01(\t\x12\x31\n\x0bmodule_type\x18\x02 \x01(\x0e\x32\x1c.amplifier.module.ModuleType\"U\n\x18GetMountedModuleResponse\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12*\n\x04info\x18\x02 \x01(\x0b\x32\x1c.amplifier.module.ModuleInfo\"=\n\x19RegisterCapabilityRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\nvalue_json\x18\x02 \x01(\t\"$\n\x14GetCapabilityRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\":\n\x15GetCapabilityResponse\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x12\n\nvalue_json\x18\x02 \x01(\t*\xbc\x01\n\nModuleType\x12\x1b\n\x17MODULE_TYPE_UNSPECIFIED\x10\x00\x12\x18\n\x14MODULE_TYPE_PROVIDER\x10\x01\x12\x14\n\x10MODULE_TYPE_TOOL\x10\x02\x12\x14\n\x10MODULE_TYPE_HOOK\x10\x03\x12\x16\n\x12MODULE_TYPE_MEMORY\x10\x04\x12\x19\n\x15MODULE_TYPE_GUARDRAIL\x10\x05\x12\x18\n\x14MODULE_TYPE_APPROVAL\x10\x06*\x82\x01\n\x0cHealthStatus\x12\x1d\n\x19HEALTH_STATUS_UNSPECIFIED\x10\x00\x12\x19\n\x15HEALTH_STATUS_SERVING\x10\x01\x12\x1d\n\x19HEALTH_STATUS_NOT_SERVING\x10\x02\x12\x19\n\x15HEALTH_STATUS_UNKNOWN\x10\x03*\xad\x01\n\x0f\x43onfigFieldType\x12!\n\x1d\x43ONFIG_FIELD_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x43ONFIG_FIELD_TYPE_STRING\x10\x01\x12\x1c\n\x18\x43ONFIG_FIELD_TYPE_NUMBER\x10\x02\x12\x1d\n\x19\x43ONFIG_FIELD_TYPE_BOOLEAN\x10\x03\x12\x1c\n\x18\x43ONFIG_FIELD_TYPE_SECRET\x10\x04*\xd8\x02\n\x11ProviderErrorType\x12#\n\x1fPROVIDER_ERROR_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18PROVIDER_ERROR_TYPE_AUTH\x10\x01\x12\"\n\x1ePROVIDER_ERROR_TYPE_RATE_LIMIT\x10\x02\x12&\n\"PROVIDER_ERROR_TYPE_CONTEXT_LENGTH\x10\x03\x12\'\n#PROVIDER_ERROR_TYPE_INVALID_REQUEST\x10\x04\x12&\n\"PROVIDER_ERROR_TYPE_CONTENT_FILTER\x10\x05\x12#\n\x1fPROVIDER_ERROR_TYPE_UNAVAILABLE\x10\x06\x12\x1f\n\x1bPROVIDER_ERROR_TYPE_TIMEOUT\x10\x07\x12\x1d\n\x19PROVIDER_ERROR_TYPE_OTHER\x10\x08*\x8c\x01\n\rToolErrorType\x12\x1f\n\x1bTOOL_ERROR_TYPE_UNSPECIFIED\x10\x00\x12\x1d\n\x19TOOL_ERROR_TYPE_EXECUTION\x10\x01\x12\x1e\n\x1aTOOL_ERROR_TYPE_VALIDATION\x10\x02\x12\x1b\n\x17TOOL_ERROR_TYPE_TIMEOUT\x10\x03*\x8c\x01\n\rHookErrorType\x12\x1f\n\x1bHOOK_ERROR_TYPE_UNSPECIFIED\x10\x00\x12\x1d\n\x19HOOK_ERROR_TYPE_EXECUTION\x10\x01\x12\x1e\n\x1aHOOK_ERROR_TYPE_VALIDATION\x10\x02\x12\x1b\n\x17HOOK_ERROR_TYPE_TIMEOUT\x10\x03*\x86\x01\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04\x12\x11\n\rROLE_FUNCTION\x10\x05\x12\x12\n\x0eROLE_DEVELOPER\x10\x06*o\n\nVisibility\x12\x1a\n\x16VISIBILITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eVISIBILITY_ALL\x10\x01\x12\x17\n\x13VISIBILITY_LLM_ONLY\x10\x02\x12\x18\n\x14VISIBILITY_USER_ONLY\x10\x03*\xab\x01\n\nHookAction\x12\x1b\n\x17HOOK_ACTION_UNSPECIFIED\x10\x00\x12\x18\n\x14HOOK_ACTION_CONTINUE\x10\x01\x12\x16\n\x12HOOK_ACTION_MODIFY\x10\x02\x12\x14\n\x10HOOK_ACTION_DENY\x10\x03\x12\x1e\n\x1aHOOK_ACTION_INJECT_CONTEXT\x10\x04\x12\x18\n\x14HOOK_ACTION_ASK_USER\x10\x05*\xa8\x01\n\x14\x43ontextInjectionRole\x12&\n\"CONTEXT_INJECTION_ROLE_UNSPECIFIED\x10\x00\x12!\n\x1d\x43ONTEXT_INJECTION_ROLE_SYSTEM\x10\x01\x12\x1f\n\x1b\x43ONTEXT_INJECTION_ROLE_USER\x10\x02\x12$\n CONTEXT_INJECTION_ROLE_ASSISTANT\x10\x03*l\n\x0f\x41pprovalDefault\x12 \n\x1c\x41PPROVAL_DEFAULT_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x41PPROVAL_DEFAULT_APPROVE\x10\x01\x12\x19\n\x15\x41PPROVAL_DEFAULT_DENY\x10\x02*\x91\x01\n\x10UserMessageLevel\x12\"\n\x1eUSER_MESSAGE_LEVEL_UNSPECIFIED\x10\x00\x12\x1b\n\x17USER_MESSAGE_LEVEL_INFO\x10\x01\x12\x1e\n\x1aUSER_MESSAGE_LEVEL_WARNING\x10\x02\x12\x1c\n\x18USER_MESSAGE_LEVEL_ERROR\x10\x03\x32\xa5\x01\n\x0bToolService\x12>\n\x07GetSpec\x12\x17.amplifier.module.Empty\x1a\x1a.amplifier.module.ToolSpec\x12V\n\x07\x45xecute\x12$.amplifier.module.ToolExecuteRequest\x1a%.amplifier.module.ToolExecuteResponse2\x9f\x03\n\x0fProviderService\x12\x42\n\x07GetInfo\x12\x17.amplifier.module.Empty\x1a\x1e.amplifier.module.ProviderInfo\x12K\n\nListModels\x12\x17.amplifier.module.Empty\x1a$.amplifier.module.ListModelsResponse\x12I\n\x08\x43omplete\x12\x1d.amplifier.module.ChatRequest\x1a\x1e.amplifier.module.ChatResponse\x12T\n\x11\x43ompleteStreaming\x12\x1d.amplifier.module.ChatRequest\x1a\x1e.amplifier.module.ChatResponse0\x01\x12Z\n\x0eParseToolCalls\x12\x1e.amplifier.module.ChatResponse\x1a(.amplifier.module.ParseToolCallsResponse2}\n\x13OrchestratorService\x12\x66\n\x07\x45xecute\x12,.amplifier.module.OrchestratorExecuteRequest\x1a-.amplifier.module.OrchestratorExecuteResponse2\xa3\x03\n\x0e\x43ontextService\x12J\n\nAddMessage\x12#.amplifier.module.AddMessageRequest\x1a\x17.amplifier.module.Empty\x12M\n\x0bGetMessages\x12\x17.amplifier.module.Empty\x1a%.amplifier.module.GetMessagesResponse\x12m\n\x15GetMessagesForRequest\x12-.amplifier.module.GetMessagesForRequestParams\x1a%.amplifier.module.GetMessagesResponse\x12L\n\x0bSetMessages\x12$.amplifier.module.SetMessagesRequest\x1a\x17.amplifier.module.Empty\x12\x39\n\x05\x43lear\x12\x17.amplifier.module.Empty\x1a\x17.amplifier.module.Empty2\xc5\x01\n\x0bHookService\x12K\n\x06Handle\x12#.amplifier.module.HookHandleRequest\x1a\x1c.amplifier.module.HookResult\x12i\n\x10GetSubscriptions\x12).amplifier.module.GetSubscriptionsRequest\x1a*.amplifier.module.GetSubscriptionsResponse2k\n\x0f\x41pprovalService\x12X\n\x0fRequestApproval\x12!.amplifier.module.ApprovalRequest\x1a\".amplifier.module.ApprovalResponse2\xd0\x07\n\rKernelService\x12\x65\n\x14\x43ompleteWithProvider\x12-.amplifier.module.CompleteWithProviderRequest\x1a\x1e.amplifier.module.ChatResponse\x12p\n\x1d\x43ompleteWithProviderStreaming\x12-.amplifier.module.CompleteWithProviderRequest\x1a\x1e.amplifier.module.ChatResponse0\x01\x12Q\n\x0b\x45xecuteTool\x12$.amplifier.module.ExecuteToolRequest\x1a\x1c.amplifier.module.ToolResult\x12K\n\x08\x45mitHook\x12!.amplifier.module.EmitHookRequest\x1a\x1c.amplifier.module.HookResult\x12o\n\x12\x45mitHookAndCollect\x12+.amplifier.module.EmitHookAndCollectRequest\x1a,.amplifier.module.EmitHookAndCollectResponse\x12Z\n\x0bGetMessages\x12$.amplifier.module.GetMessagesRequest\x1a%.amplifier.module.GetMessagesResponse\x12P\n\nAddMessage\x12).amplifier.module.KernelAddMessageRequest\x1a\x17.amplifier.module.Empty\x12i\n\x10GetMountedModule\x12).amplifier.module.GetMountedModuleRequest\x1a*.amplifier.module.GetMountedModuleResponse\x12Z\n\x12RegisterCapability\x12+.amplifier.module.RegisterCapabilityRequest\x1a\x17.amplifier.module.Empty\x12`\n\rGetCapability\x12&.amplifier.module.GetCapabilityRequest\x1a\'.amplifier.module.GetCapabilityResponse2\xaf\x02\n\x0fModuleLifecycle\x12H\n\x05Mount\x12\x1e.amplifier.module.MountRequest\x1a\x1f.amplifier.module.MountResponse\x12;\n\x07\x43leanup\x12\x17.amplifier.module.Empty\x1a\x17.amplifier.module.Empty\x12M\n\x0bHealthCheck\x12\x17.amplifier.module.Empty\x1a%.amplifier.module.HealthCheckResponse\x12\x46\n\rGetModuleInfo\x12\x17.amplifier.module.Empty\x1a\x1c.amplifier.module.ModuleInfob\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x61mplifier_module.proto\x12\x10\x61mplifier.module\"\x07\n\x05\x45mpty\"F\n\x08ToolSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x17\n\x0fparameters_json\x18\x03 \x01(\t\"9\n\x12ToolExecuteRequest\x12\r\n\x05input\x18\x01 \x01(\x0c\x12\x14\n\x0c\x63ontent_type\x18\x02 \x01(\t\"[\n\x13ToolExecuteResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0e\n\x06output\x18\x02 \x01(\x0c\x12\x14\n\x0c\x63ontent_type\x18\x03 \x01(\t\x12\r\n\x05\x65rror\x18\x04 \x01(\t\"\xd6\x01\n\nModuleInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t\x12\x31\n\x0bmodule_type\x18\x04 \x01(\x0e\x32\x1c.amplifier.module.ModuleType\x12\x13\n\x0bmount_point\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t\x12\x1a\n\x12\x63onfig_schema_json\x18\x07 \x01(\t\x12\x14\n\x0c\x63\x61pabilities\x18\x08 \x03(\t\x12\x0e\n\x06\x61uthor\x18\t \x01(\t\"\x8c\x01\n\x0cMountRequest\x12:\n\x06\x63onfig\x18\x01 \x03(\x0b\x32*.amplifier.module.MountRequest.ConfigEntry\x12\x11\n\tmodule_id\x18\x02 \x01(\t\x1a-\n\x0b\x43onfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"_\n\rMountResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12.\n\x06status\x18\x03 \x01(\x0e\x32\x1e.amplifier.module.HealthStatus\"V\n\x13HealthCheckResponse\x12.\n\x06status\x18\x01 \x01(\x0e\x32\x1e.amplifier.module.HealthStatus\x12\x0f\n\x07message\x18\x02 \x01(\t\"\xca\x02\n\x0b\x43onfigField\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x35\n\nfield_type\x18\x03 \x01(\x0e\x32!.amplifier.module.ConfigFieldType\x12\x0e\n\x06prompt\x18\x04 \x01(\t\x12\x0f\n\x07\x65nv_var\x18\x05 \x01(\t\x12\x0f\n\x07\x63hoices\x18\x06 \x03(\t\x12\x10\n\x08required\x18\x07 \x01(\x08\x12\x15\n\rdefault_value\x18\x08 \x01(\t\x12>\n\tshow_when\x18\t \x03(\x0b\x32+.amplifier.module.ConfigField.ShowWhenEntry\x12\x16\n\x0erequires_model\x18\n \x01(\x08\x1a/\n\rShowWhenEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xbc\x01\n\rProviderError\x12\x37\n\nerror_type\x18\x01 \x01(\x0e\x32#.amplifier.module.ProviderErrorType\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x15\n\rprovider_name\x18\x03 \x01(\t\x12\r\n\x05model\x18\x04 \x01(\t\x12\x13\n\x0bstatus_code\x18\x05 \x01(\x05\x12\x11\n\tretryable\x18\x06 \x01(\x08\x12\x13\n\x0bretry_after\x18\x07 \x01(\x01\"\x97\x01\n\tToolError\x12\x33\n\nerror_type\x18\x01 \x01(\x0e\x32\x1f.amplifier.module.ToolErrorType\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x11\n\ttool_name\x18\x03 \x01(\t\x12\x0e\n\x06stdout\x18\x04 \x01(\t\x12\x0e\n\x06stderr\x18\x05 \x01(\t\x12\x11\n\texit_code\x18\x06 \x01(\x05\"d\n\tHookError\x12\x33\n\nerror_type\x18\x01 \x01(\x0e\x32\x1f.amplifier.module.HookErrorType\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x11\n\thook_name\x18\x03 \x01(\t\"\xef\x01\n\x0e\x41mplifierError\x12\x39\n\x0eprovider_error\x18\x01 \x01(\x0b\x32\x1f.amplifier.module.ProviderErrorH\x00\x12\x31\n\ntool_error\x18\x02 \x01(\x0b\x32\x1b.amplifier.module.ToolErrorH\x00\x12\x31\n\nhook_error\x18\x03 \x01(\x0b\x32\x1b.amplifier.module.HookErrorH\x00\x12\x17\n\rgeneric_error\x18\x04 \x01(\tH\x00\x12\x1a\n\x10validation_error\x18\x05 \x01(\tH\x00\x42\x07\n\x05\x65rror\"\x19\n\tTextBlock\x12\x0c\n\x04text\x18\x01 \x01(\t\"E\n\rThinkingBlock\x12\x10\n\x08thinking\x18\x01 \x01(\t\x12\x11\n\tsignature\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\"%\n\x15RedactedThinkingBlock\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\t\"=\n\rToolCallBlock\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x12\n\ninput_json\x18\x03 \x01(\t\"<\n\x0fToolResultBlock\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x13\n\x0boutput_json\x18\x02 \x01(\t\"C\n\nImageBlock\x12\x12\n\nmedia_type\x18\x01 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\x13\n\x0bsource_json\x18\x03 \x01(\t\"2\n\x0eReasoningBlock\x12\x0f\n\x07\x63ontent\x18\x01 \x03(\t\x12\x0f\n\x07summary\x18\x02 \x03(\t\"\xf1\x03\n\x0c\x43ontentBlock\x12\x31\n\ntext_block\x18\x01 \x01(\x0b\x32\x1b.amplifier.module.TextBlockH\x00\x12\x39\n\x0ethinking_block\x18\x02 \x01(\x0b\x32\x1f.amplifier.module.ThinkingBlockH\x00\x12J\n\x17redacted_thinking_block\x18\x03 \x01(\x0b\x32\'.amplifier.module.RedactedThinkingBlockH\x00\x12:\n\x0ftool_call_block\x18\x04 \x01(\x0b\x32\x1f.amplifier.module.ToolCallBlockH\x00\x12>\n\x11tool_result_block\x18\x05 \x01(\x0b\x32!.amplifier.module.ToolResultBlockH\x00\x12\x33\n\x0bimage_block\x18\x06 \x01(\x0b\x32\x1c.amplifier.module.ImageBlockH\x00\x12;\n\x0freasoning_block\x18\x07 \x01(\x0b\x32 .amplifier.module.ReasoningBlockH\x00\x12\x30\n\nvisibility\x18\x08 \x01(\x0e\x32\x1c.amplifier.module.VisibilityB\x07\n\x05\x62lock\"B\n\x10\x43ontentBlockList\x12.\n\x06\x62locks\x18\x01 \x03(\x0b\x32\x1e.amplifier.module.ContentBlock\"\xca\x01\n\x07Message\x12$\n\x04role\x18\x01 \x01(\x0e\x32\x16.amplifier.module.Role\x12\x16\n\x0ctext_content\x18\x02 \x01(\tH\x00\x12;\n\rblock_content\x18\x03 \x01(\x0b\x32\".amplifier.module.ContentBlockListH\x00\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x14\n\x0ctool_call_id\x18\x05 \x01(\t\x12\x15\n\rmetadata_json\x18\x06 \x01(\tB\t\n\x07\x63ontent\"C\n\x0fToolCallMessage\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"K\n\rToolSpecProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x17\n\x0fparameters_json\x18\x03 \x01(\t\"7\n\x10JsonSchemaFormat\x12\x13\n\x0bschema_json\x18\x01 \x01(\t\x12\x0e\n\x06strict\x18\x02 \x01(\x08\"u\n\x0eResponseFormat\x12\x0e\n\x04text\x18\x01 \x01(\x08H\x00\x12\x0e\n\x04json\x18\x02 \x01(\x08H\x00\x12\x39\n\x0bjson_schema\x18\x03 \x01(\x0b\x32\".amplifier.module.JsonSchemaFormatH\x00\x42\x08\n\x06\x66ormat\"\x9b\x02\n\x05Usage\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\x12\x1d\n\x10reasoning_tokens\x18\x04 \x01(\x05H\x00\x88\x01\x01\x12\x1e\n\x11\x63\x61\x63he_read_tokens\x18\x05 \x01(\x05H\x01\x88\x01\x01\x12\"\n\x15\x63\x61\x63he_creation_tokens\x18\x06 \x01(\x05H\x02\x88\x01\x01\x12\x15\n\x08\x63ost_usd\x18\x07 \x01(\tH\x03\x88\x01\x01\x42\x13\n\x11_reasoning_tokensB\x14\n\x12_cache_read_tokensB\x18\n\x16_cache_creation_tokensB\x0b\n\t_cost_usd\"@\n\x0b\x44\x65gradation\x12\x11\n\trequested\x18\x01 \x01(\t\x12\x0e\n\x06\x61\x63tual\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\"\x81\x03\n\x0b\x43hatRequest\x12+\n\x08messages\x18\x01 \x03(\x0b\x32\x19.amplifier.module.Message\x12.\n\x05tools\x18\x02 \x03(\x0b\x32\x1f.amplifier.module.ToolSpecProto\x12\x39\n\x0fresponse_format\x18\x03 \x01(\x0b\x32 .amplifier.module.ResponseFormat\x12\x13\n\x0btemperature\x18\x04 \x01(\x01\x12\r\n\x05top_p\x18\x05 \x01(\x01\x12\x19\n\x11max_output_tokens\x18\x06 \x01(\x05\x12\x17\n\x0f\x63onversation_id\x18\x07 \x01(\t\x12\x0e\n\x06stream\x18\x08 \x01(\x08\x12\x15\n\rmetadata_json\x18\t \x01(\t\x12\r\n\x05model\x18\n \x01(\t\x12\x13\n\x0btool_choice\x18\x0b \x01(\t\x12\x0c\n\x04stop\x18\x0c \x03(\t\x12\x18\n\x10reasoning_effort\x18\r \x01(\t\x12\x0f\n\x07timeout\x18\x0e \x01(\x01\"\x98\x02\n\x0c\x43hatResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x35\n\ntool_calls\x18\x02 \x03(\x0b\x32!.amplifier.module.ToolCallMessage\x12&\n\x05usage\x18\x03 \x01(\x0b\x32\x17.amplifier.module.Usage\x12\x32\n\x0b\x64\x65gradation\x18\x04 \x01(\x0b\x32\x1d.amplifier.module.Degradation\x12\x15\n\rfinish_reason\x18\x05 \x01(\t\x12\x15\n\rmetadata_json\x18\x06 \x01(\t\x12\x36\n\x0e\x63ontent_blocks\x18\x07 \x03(\x0b\x32\x1e.amplifier.module.ContentBlock\"F\n\nToolResult\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x13\n\x0boutput_json\x18\x02 \x01(\t\x12\x12\n\nerror_json\x18\x03 \x01(\t\"\xa7\x04\n\nHookResult\x12,\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\x1c.amplifier.module.HookAction\x12\x11\n\tdata_json\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x19\n\x11\x63ontext_injection\x18\x04 \x01(\t\x12\x46\n\x16\x63ontext_injection_role\x18\x05 \x01(\x0e\x32&.amplifier.module.ContextInjectionRole\x12\x11\n\tephemeral\x18\x06 \x01(\x08\x12\x17\n\x0f\x61pproval_prompt\x18\x07 \x01(\t\x12\x18\n\x10\x61pproval_options\x18\x08 \x03(\t\x12\x1d\n\x10\x61pproval_timeout\x18\t \x01(\x01H\x00\x88\x01\x01\x12;\n\x10\x61pproval_default\x18\n \x01(\x0e\x32!.amplifier.module.ApprovalDefault\x12\x17\n\x0fsuppress_output\x18\x0b \x01(\x08\x12\x14\n\x0cuser_message\x18\x0c \x01(\t\x12>\n\x12user_message_level\x18\r \x01(\x0e\x32\".amplifier.module.UserMessageLevel\x12\x1b\n\x13user_message_source\x18\x0e \x01(\t\x12\"\n\x1a\x61ppend_to_last_tool_result\x18\x0f \x01(\x08\x42\x13\n\x11_approval_timeout\"\x8d\x01\n\tModelInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x16\n\x0e\x63ontext_window\x18\x03 \x01(\x05\x12\x19\n\x11max_output_tokens\x18\x04 \x01(\x05\x12\x14\n\x0c\x63\x61pabilities\x18\x05 \x03(\t\x12\x15\n\rdefaults_json\x18\x06 \x01(\t\"\xb0\x01\n\x0cProviderInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x1b\n\x13\x63redential_env_vars\x18\x03 \x03(\t\x12\x14\n\x0c\x63\x61pabilities\x18\x04 \x03(\t\x12\x15\n\rdefaults_json\x18\x05 \x01(\t\x12\x34\n\rconfig_fields\x18\x06 \x03(\x0b\x32\x1d.amplifier.module.ConfigField\"\x80\x01\n\x0f\x41pprovalRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x0e\n\x06\x61\x63tion\x18\x02 \x01(\t\x12\x14\n\x0c\x64\x65tails_json\x18\x03 \x01(\t\x12\x12\n\nrisk_level\x18\x04 \x01(\t\x12\x14\n\x07timeout\x18\x05 \x01(\x01H\x00\x88\x01\x01\x42\n\n\x08_timeout\"F\n\x10\x41pprovalResponse\x12\x10\n\x08\x61pproved\x18\x01 \x01(\x08\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x10\n\x08remember\x18\x03 \x01(\x08\"A\n\x12ListModelsResponse\x12+\n\x06models\x18\x01 \x03(\x0b\x32\x1b.amplifier.module.ModelInfo\"O\n\x16ParseToolCallsResponse\x12\x35\n\ntool_calls\x18\x01 \x03(\x0b\x32!.amplifier.module.ToolCallMessage\"@\n\x1aOrchestratorExecuteRequest\x12\x0e\n\x06prompt\x18\x01 \x01(\t\x12\x12\n\nsession_id\x18\x02 \x01(\t\">\n\x1bOrchestratorExecuteResponse\x12\x10\n\x08response\x18\x01 \x01(\t\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"?\n\x11\x41\x64\x64MessageRequest\x12*\n\x07message\x18\x01 \x01(\x0b\x32\x19.amplifier.module.Message\"B\n\x13GetMessagesResponse\x12+\n\x08messages\x18\x01 \x03(\x0b\x32\x19.amplifier.module.Message\"J\n\x1bGetMessagesForRequestParams\x12\x14\n\x0ctoken_budget\x18\x01 \x01(\x05\x12\x15\n\rprovider_name\x18\x02 \x01(\t\"A\n\x12SetMessagesRequest\x12+\n\x08messages\x18\x01 \x03(\x0b\x32\x19.amplifier.module.Message\"5\n\x11HookHandleRequest\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\tdata_json\x18\x02 \x01(\t\".\n\x17GetSubscriptionsRequest\x12\x13\n\x0b\x63onfig_json\x18\x01 \x01(\t\"V\n\x18GetSubscriptionsResponse\x12:\n\rsubscriptions\x18\x01 \x03(\x0b\x32#.amplifier.module.EventSubscription\"B\n\x11\x45ventSubscription\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x10\n\x08priority\x18\x02 \x01(\x05\x12\x0c\n\x04name\x18\x03 \x01(\t\"d\n\x1b\x43ompleteWithProviderRequest\x12\x15\n\rprovider_name\x18\x01 \x01(\t\x12.\n\x07request\x18\x02 \x01(\x0b\x32\x1d.amplifier.module.ChatRequest\";\n\x12\x45xecuteToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x12\n\ninput_json\x18\x02 \x01(\t\"3\n\x0f\x45mitHookRequest\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\tdata_json\x18\x02 \x01(\t\"V\n\x19\x45mitHookAndCollectRequest\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\tdata_json\x18\x02 \x01(\t\x12\x17\n\x0ftimeout_seconds\x18\x03 \x01(\x01\"4\n\x1a\x45mitHookAndCollectResponse\x12\x16\n\x0eresponses_json\x18\x01 \x03(\t\"(\n\x12GetMessagesRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"Y\n\x17KernelAddMessageRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12*\n\x07message\x18\x02 \x01(\x0b\x32\x19.amplifier.module.Message\"a\n\x17GetMountedModuleRequest\x12\x13\n\x0bmodule_name\x18\x01 \x01(\t\x12\x31\n\x0bmodule_type\x18\x02 \x01(\x0e\x32\x1c.amplifier.module.ModuleType\"U\n\x18GetMountedModuleResponse\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12*\n\x04info\x18\x02 \x01(\x0b\x32\x1c.amplifier.module.ModuleInfo\"=\n\x19RegisterCapabilityRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\nvalue_json\x18\x02 \x01(\t\"$\n\x14GetCapabilityRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\":\n\x15GetCapabilityResponse\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x12\n\nvalue_json\x18\x02 \x01(\t*\xbc\x01\n\nModuleType\x12\x1b\n\x17MODULE_TYPE_UNSPECIFIED\x10\x00\x12\x18\n\x14MODULE_TYPE_PROVIDER\x10\x01\x12\x14\n\x10MODULE_TYPE_TOOL\x10\x02\x12\x14\n\x10MODULE_TYPE_HOOK\x10\x03\x12\x16\n\x12MODULE_TYPE_MEMORY\x10\x04\x12\x19\n\x15MODULE_TYPE_GUARDRAIL\x10\x05\x12\x18\n\x14MODULE_TYPE_APPROVAL\x10\x06*\x82\x01\n\x0cHealthStatus\x12\x1d\n\x19HEALTH_STATUS_UNSPECIFIED\x10\x00\x12\x19\n\x15HEALTH_STATUS_SERVING\x10\x01\x12\x1d\n\x19HEALTH_STATUS_NOT_SERVING\x10\x02\x12\x19\n\x15HEALTH_STATUS_UNKNOWN\x10\x03*\xad\x01\n\x0f\x43onfigFieldType\x12!\n\x1d\x43ONFIG_FIELD_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x43ONFIG_FIELD_TYPE_STRING\x10\x01\x12\x1c\n\x18\x43ONFIG_FIELD_TYPE_NUMBER\x10\x02\x12\x1d\n\x19\x43ONFIG_FIELD_TYPE_BOOLEAN\x10\x03\x12\x1c\n\x18\x43ONFIG_FIELD_TYPE_SECRET\x10\x04*\xd8\x02\n\x11ProviderErrorType\x12#\n\x1fPROVIDER_ERROR_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18PROVIDER_ERROR_TYPE_AUTH\x10\x01\x12\"\n\x1ePROVIDER_ERROR_TYPE_RATE_LIMIT\x10\x02\x12&\n\"PROVIDER_ERROR_TYPE_CONTEXT_LENGTH\x10\x03\x12\'\n#PROVIDER_ERROR_TYPE_INVALID_REQUEST\x10\x04\x12&\n\"PROVIDER_ERROR_TYPE_CONTENT_FILTER\x10\x05\x12#\n\x1fPROVIDER_ERROR_TYPE_UNAVAILABLE\x10\x06\x12\x1f\n\x1bPROVIDER_ERROR_TYPE_TIMEOUT\x10\x07\x12\x1d\n\x19PROVIDER_ERROR_TYPE_OTHER\x10\x08*\x8c\x01\n\rToolErrorType\x12\x1f\n\x1bTOOL_ERROR_TYPE_UNSPECIFIED\x10\x00\x12\x1d\n\x19TOOL_ERROR_TYPE_EXECUTION\x10\x01\x12\x1e\n\x1aTOOL_ERROR_TYPE_VALIDATION\x10\x02\x12\x1b\n\x17TOOL_ERROR_TYPE_TIMEOUT\x10\x03*\x8c\x01\n\rHookErrorType\x12\x1f\n\x1bHOOK_ERROR_TYPE_UNSPECIFIED\x10\x00\x12\x1d\n\x19HOOK_ERROR_TYPE_EXECUTION\x10\x01\x12\x1e\n\x1aHOOK_ERROR_TYPE_VALIDATION\x10\x02\x12\x1b\n\x17HOOK_ERROR_TYPE_TIMEOUT\x10\x03*\x86\x01\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04\x12\x11\n\rROLE_FUNCTION\x10\x05\x12\x12\n\x0eROLE_DEVELOPER\x10\x06*o\n\nVisibility\x12\x1a\n\x16VISIBILITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eVISIBILITY_ALL\x10\x01\x12\x17\n\x13VISIBILITY_LLM_ONLY\x10\x02\x12\x18\n\x14VISIBILITY_USER_ONLY\x10\x03*\xab\x01\n\nHookAction\x12\x1b\n\x17HOOK_ACTION_UNSPECIFIED\x10\x00\x12\x18\n\x14HOOK_ACTION_CONTINUE\x10\x01\x12\x16\n\x12HOOK_ACTION_MODIFY\x10\x02\x12\x14\n\x10HOOK_ACTION_DENY\x10\x03\x12\x1e\n\x1aHOOK_ACTION_INJECT_CONTEXT\x10\x04\x12\x18\n\x14HOOK_ACTION_ASK_USER\x10\x05*\xa8\x01\n\x14\x43ontextInjectionRole\x12&\n\"CONTEXT_INJECTION_ROLE_UNSPECIFIED\x10\x00\x12!\n\x1d\x43ONTEXT_INJECTION_ROLE_SYSTEM\x10\x01\x12\x1f\n\x1b\x43ONTEXT_INJECTION_ROLE_USER\x10\x02\x12$\n CONTEXT_INJECTION_ROLE_ASSISTANT\x10\x03*l\n\x0f\x41pprovalDefault\x12 \n\x1c\x41PPROVAL_DEFAULT_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x41PPROVAL_DEFAULT_APPROVE\x10\x01\x12\x19\n\x15\x41PPROVAL_DEFAULT_DENY\x10\x02*\x91\x01\n\x10UserMessageLevel\x12\"\n\x1eUSER_MESSAGE_LEVEL_UNSPECIFIED\x10\x00\x12\x1b\n\x17USER_MESSAGE_LEVEL_INFO\x10\x01\x12\x1e\n\x1aUSER_MESSAGE_LEVEL_WARNING\x10\x02\x12\x1c\n\x18USER_MESSAGE_LEVEL_ERROR\x10\x03\x32\xa5\x01\n\x0bToolService\x12>\n\x07GetSpec\x12\x17.amplifier.module.Empty\x1a\x1a.amplifier.module.ToolSpec\x12V\n\x07\x45xecute\x12$.amplifier.module.ToolExecuteRequest\x1a%.amplifier.module.ToolExecuteResponse2\x9f\x03\n\x0fProviderService\x12\x42\n\x07GetInfo\x12\x17.amplifier.module.Empty\x1a\x1e.amplifier.module.ProviderInfo\x12K\n\nListModels\x12\x17.amplifier.module.Empty\x1a$.amplifier.module.ListModelsResponse\x12I\n\x08\x43omplete\x12\x1d.amplifier.module.ChatRequest\x1a\x1e.amplifier.module.ChatResponse\x12T\n\x11\x43ompleteStreaming\x12\x1d.amplifier.module.ChatRequest\x1a\x1e.amplifier.module.ChatResponse0\x01\x12Z\n\x0eParseToolCalls\x12\x1e.amplifier.module.ChatResponse\x1a(.amplifier.module.ParseToolCallsResponse2}\n\x13OrchestratorService\x12\x66\n\x07\x45xecute\x12,.amplifier.module.OrchestratorExecuteRequest\x1a-.amplifier.module.OrchestratorExecuteResponse2\xa3\x03\n\x0e\x43ontextService\x12J\n\nAddMessage\x12#.amplifier.module.AddMessageRequest\x1a\x17.amplifier.module.Empty\x12M\n\x0bGetMessages\x12\x17.amplifier.module.Empty\x1a%.amplifier.module.GetMessagesResponse\x12m\n\x15GetMessagesForRequest\x12-.amplifier.module.GetMessagesForRequestParams\x1a%.amplifier.module.GetMessagesResponse\x12L\n\x0bSetMessages\x12$.amplifier.module.SetMessagesRequest\x1a\x17.amplifier.module.Empty\x12\x39\n\x05\x43lear\x12\x17.amplifier.module.Empty\x1a\x17.amplifier.module.Empty2\xc5\x01\n\x0bHookService\x12K\n\x06Handle\x12#.amplifier.module.HookHandleRequest\x1a\x1c.amplifier.module.HookResult\x12i\n\x10GetSubscriptions\x12).amplifier.module.GetSubscriptionsRequest\x1a*.amplifier.module.GetSubscriptionsResponse2k\n\x0f\x41pprovalService\x12X\n\x0fRequestApproval\x12!.amplifier.module.ApprovalRequest\x1a\".amplifier.module.ApprovalResponse2\xd0\x07\n\rKernelService\x12\x65\n\x14\x43ompleteWithProvider\x12-.amplifier.module.CompleteWithProviderRequest\x1a\x1e.amplifier.module.ChatResponse\x12p\n\x1d\x43ompleteWithProviderStreaming\x12-.amplifier.module.CompleteWithProviderRequest\x1a\x1e.amplifier.module.ChatResponse0\x01\x12Q\n\x0b\x45xecuteTool\x12$.amplifier.module.ExecuteToolRequest\x1a\x1c.amplifier.module.ToolResult\x12K\n\x08\x45mitHook\x12!.amplifier.module.EmitHookRequest\x1a\x1c.amplifier.module.HookResult\x12o\n\x12\x45mitHookAndCollect\x12+.amplifier.module.EmitHookAndCollectRequest\x1a,.amplifier.module.EmitHookAndCollectResponse\x12Z\n\x0bGetMessages\x12$.amplifier.module.GetMessagesRequest\x1a%.amplifier.module.GetMessagesResponse\x12P\n\nAddMessage\x12).amplifier.module.KernelAddMessageRequest\x1a\x17.amplifier.module.Empty\x12i\n\x10GetMountedModule\x12).amplifier.module.GetMountedModuleRequest\x1a*.amplifier.module.GetMountedModuleResponse\x12Z\n\x12RegisterCapability\x12+.amplifier.module.RegisterCapabilityRequest\x1a\x17.amplifier.module.Empty\x12`\n\rGetCapability\x12&.amplifier.module.GetCapabilityRequest\x1a\'.amplifier.module.GetCapabilityResponse2\xaf\x02\n\x0fModuleLifecycle\x12H\n\x05Mount\x12\x1e.amplifier.module.MountRequest\x1a\x1f.amplifier.module.MountResponse\x12;\n\x07\x43leanup\x12\x17.amplifier.module.Empty\x1a\x17.amplifier.module.Empty\x12M\n\x0bHealthCheck\x12\x17.amplifier.module.Empty\x1a%.amplifier.module.HealthCheckResponse\x12\x46\n\rGetModuleInfo\x12\x17.amplifier.module.Empty\x1a\x1c.amplifier.module.ModuleInfob\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -35,30 +35,30 @@ _globals['_MOUNTREQUEST_CONFIGENTRY']._serialized_options = b'8\001' _globals['_CONFIGFIELD_SHOWWHENENTRY']._loaded_options = None _globals['_CONFIGFIELD_SHOWWHENENTRY']._serialized_options = b'8\001' - _globals['_MODULETYPE']._serialized_start=7113 - _globals['_MODULETYPE']._serialized_end=7301 - _globals['_HEALTHSTATUS']._serialized_start=7304 - _globals['_HEALTHSTATUS']._serialized_end=7434 - _globals['_CONFIGFIELDTYPE']._serialized_start=7437 - _globals['_CONFIGFIELDTYPE']._serialized_end=7610 - _globals['_PROVIDERERRORTYPE']._serialized_start=7613 - _globals['_PROVIDERERRORTYPE']._serialized_end=7957 - _globals['_TOOLERRORTYPE']._serialized_start=7960 - _globals['_TOOLERRORTYPE']._serialized_end=8100 - _globals['_HOOKERRORTYPE']._serialized_start=8103 - _globals['_HOOKERRORTYPE']._serialized_end=8243 - _globals['_ROLE']._serialized_start=8246 - _globals['_ROLE']._serialized_end=8380 - _globals['_VISIBILITY']._serialized_start=8382 - _globals['_VISIBILITY']._serialized_end=8493 - _globals['_HOOKACTION']._serialized_start=8496 - _globals['_HOOKACTION']._serialized_end=8667 - _globals['_CONTEXTINJECTIONROLE']._serialized_start=8670 - _globals['_CONTEXTINJECTIONROLE']._serialized_end=8838 - _globals['_APPROVALDEFAULT']._serialized_start=8840 - _globals['_APPROVALDEFAULT']._serialized_end=8948 - _globals['_USERMESSAGELEVEL']._serialized_start=8951 - _globals['_USERMESSAGELEVEL']._serialized_end=9096 + _globals['_MODULETYPE']._serialized_start=7149 + _globals['_MODULETYPE']._serialized_end=7337 + _globals['_HEALTHSTATUS']._serialized_start=7340 + _globals['_HEALTHSTATUS']._serialized_end=7470 + _globals['_CONFIGFIELDTYPE']._serialized_start=7473 + _globals['_CONFIGFIELDTYPE']._serialized_end=7646 + _globals['_PROVIDERERRORTYPE']._serialized_start=7649 + _globals['_PROVIDERERRORTYPE']._serialized_end=7993 + _globals['_TOOLERRORTYPE']._serialized_start=7996 + _globals['_TOOLERRORTYPE']._serialized_end=8136 + _globals['_HOOKERRORTYPE']._serialized_start=8139 + _globals['_HOOKERRORTYPE']._serialized_end=8279 + _globals['_ROLE']._serialized_start=8282 + _globals['_ROLE']._serialized_end=8416 + _globals['_VISIBILITY']._serialized_start=8418 + _globals['_VISIBILITY']._serialized_end=8529 + _globals['_HOOKACTION']._serialized_start=8532 + _globals['_HOOKACTION']._serialized_end=8703 + _globals['_CONTEXTINJECTIONROLE']._serialized_start=8706 + _globals['_CONTEXTINJECTIONROLE']._serialized_end=8874 + _globals['_APPROVALDEFAULT']._serialized_start=8876 + _globals['_APPROVALDEFAULT']._serialized_end=8984 + _globals['_USERMESSAGELEVEL']._serialized_start=8987 + _globals['_USERMESSAGELEVEL']._serialized_end=9132 _globals['_EMPTY']._serialized_start=44 _globals['_EMPTY']._serialized_end=51 _globals['_TOOLSPEC']._serialized_start=53 @@ -118,87 +118,87 @@ _globals['_RESPONSEFORMAT']._serialized_start=3203 _globals['_RESPONSEFORMAT']._serialized_end=3320 _globals['_USAGE']._serialized_start=3323 - _globals['_USAGE']._serialized_end=3570 - _globals['_DEGRADATION']._serialized_start=3572 - _globals['_DEGRADATION']._serialized_end=3636 - _globals['_CHATREQUEST']._serialized_start=3639 - _globals['_CHATREQUEST']._serialized_end=4024 - _globals['_CHATRESPONSE']._serialized_start=4027 - _globals['_CHATRESPONSE']._serialized_end=4307 - _globals['_TOOLRESULT']._serialized_start=4309 - _globals['_TOOLRESULT']._serialized_end=4379 - _globals['_HOOKRESULT']._serialized_start=4382 - _globals['_HOOKRESULT']._serialized_end=4933 - _globals['_MODELINFO']._serialized_start=4936 - _globals['_MODELINFO']._serialized_end=5077 - _globals['_PROVIDERINFO']._serialized_start=5080 - _globals['_PROVIDERINFO']._serialized_end=5256 - _globals['_APPROVALREQUEST']._serialized_start=5259 - _globals['_APPROVALREQUEST']._serialized_end=5387 - _globals['_APPROVALRESPONSE']._serialized_start=5389 - _globals['_APPROVALRESPONSE']._serialized_end=5459 - _globals['_LISTMODELSRESPONSE']._serialized_start=5461 - _globals['_LISTMODELSRESPONSE']._serialized_end=5526 - _globals['_PARSETOOLCALLSRESPONSE']._serialized_start=5528 - _globals['_PARSETOOLCALLSRESPONSE']._serialized_end=5607 - _globals['_ORCHESTRATOREXECUTEREQUEST']._serialized_start=5609 - _globals['_ORCHESTRATOREXECUTEREQUEST']._serialized_end=5673 - _globals['_ORCHESTRATOREXECUTERESPONSE']._serialized_start=5675 - _globals['_ORCHESTRATOREXECUTERESPONSE']._serialized_end=5737 - _globals['_ADDMESSAGEREQUEST']._serialized_start=5739 - _globals['_ADDMESSAGEREQUEST']._serialized_end=5802 - _globals['_GETMESSAGESRESPONSE']._serialized_start=5804 - _globals['_GETMESSAGESRESPONSE']._serialized_end=5870 - _globals['_GETMESSAGESFORREQUESTPARAMS']._serialized_start=5872 - _globals['_GETMESSAGESFORREQUESTPARAMS']._serialized_end=5946 - _globals['_SETMESSAGESREQUEST']._serialized_start=5948 - _globals['_SETMESSAGESREQUEST']._serialized_end=6013 - _globals['_HOOKHANDLEREQUEST']._serialized_start=6015 - _globals['_HOOKHANDLEREQUEST']._serialized_end=6068 - _globals['_GETSUBSCRIPTIONSREQUEST']._serialized_start=6070 - _globals['_GETSUBSCRIPTIONSREQUEST']._serialized_end=6116 - _globals['_GETSUBSCRIPTIONSRESPONSE']._serialized_start=6118 - _globals['_GETSUBSCRIPTIONSRESPONSE']._serialized_end=6204 - _globals['_EVENTSUBSCRIPTION']._serialized_start=6206 - _globals['_EVENTSUBSCRIPTION']._serialized_end=6272 - _globals['_COMPLETEWITHPROVIDERREQUEST']._serialized_start=6274 - _globals['_COMPLETEWITHPROVIDERREQUEST']._serialized_end=6374 - _globals['_EXECUTETOOLREQUEST']._serialized_start=6376 - _globals['_EXECUTETOOLREQUEST']._serialized_end=6435 - _globals['_EMITHOOKREQUEST']._serialized_start=6437 - _globals['_EMITHOOKREQUEST']._serialized_end=6488 - _globals['_EMITHOOKANDCOLLECTREQUEST']._serialized_start=6490 - _globals['_EMITHOOKANDCOLLECTREQUEST']._serialized_end=6576 - _globals['_EMITHOOKANDCOLLECTRESPONSE']._serialized_start=6578 - _globals['_EMITHOOKANDCOLLECTRESPONSE']._serialized_end=6630 - _globals['_GETMESSAGESREQUEST']._serialized_start=6632 - _globals['_GETMESSAGESREQUEST']._serialized_end=6672 - _globals['_KERNELADDMESSAGEREQUEST']._serialized_start=6674 - _globals['_KERNELADDMESSAGEREQUEST']._serialized_end=6763 - _globals['_GETMOUNTEDMODULEREQUEST']._serialized_start=6765 - _globals['_GETMOUNTEDMODULEREQUEST']._serialized_end=6862 - _globals['_GETMOUNTEDMODULERESPONSE']._serialized_start=6864 - _globals['_GETMOUNTEDMODULERESPONSE']._serialized_end=6949 - _globals['_REGISTERCAPABILITYREQUEST']._serialized_start=6951 - _globals['_REGISTERCAPABILITYREQUEST']._serialized_end=7012 - _globals['_GETCAPABILITYREQUEST']._serialized_start=7014 - _globals['_GETCAPABILITYREQUEST']._serialized_end=7050 - _globals['_GETCAPABILITYRESPONSE']._serialized_start=7052 - _globals['_GETCAPABILITYRESPONSE']._serialized_end=7110 - _globals['_TOOLSERVICE']._serialized_start=9099 - _globals['_TOOLSERVICE']._serialized_end=9264 - _globals['_PROVIDERSERVICE']._serialized_start=9267 - _globals['_PROVIDERSERVICE']._serialized_end=9682 - _globals['_ORCHESTRATORSERVICE']._serialized_start=9684 - _globals['_ORCHESTRATORSERVICE']._serialized_end=9809 - _globals['_CONTEXTSERVICE']._serialized_start=9812 - _globals['_CONTEXTSERVICE']._serialized_end=10231 - _globals['_HOOKSERVICE']._serialized_start=10234 - _globals['_HOOKSERVICE']._serialized_end=10431 - _globals['_APPROVALSERVICE']._serialized_start=10433 - _globals['_APPROVALSERVICE']._serialized_end=10540 - _globals['_KERNELSERVICE']._serialized_start=10543 - _globals['_KERNELSERVICE']._serialized_end=11519 - _globals['_MODULELIFECYCLE']._serialized_start=11522 - _globals['_MODULELIFECYCLE']._serialized_end=11825 + _globals['_USAGE']._serialized_end=3606 + _globals['_DEGRADATION']._serialized_start=3608 + _globals['_DEGRADATION']._serialized_end=3672 + _globals['_CHATREQUEST']._serialized_start=3675 + _globals['_CHATREQUEST']._serialized_end=4060 + _globals['_CHATRESPONSE']._serialized_start=4063 + _globals['_CHATRESPONSE']._serialized_end=4343 + _globals['_TOOLRESULT']._serialized_start=4345 + _globals['_TOOLRESULT']._serialized_end=4415 + _globals['_HOOKRESULT']._serialized_start=4418 + _globals['_HOOKRESULT']._serialized_end=4969 + _globals['_MODELINFO']._serialized_start=4972 + _globals['_MODELINFO']._serialized_end=5113 + _globals['_PROVIDERINFO']._serialized_start=5116 + _globals['_PROVIDERINFO']._serialized_end=5292 + _globals['_APPROVALREQUEST']._serialized_start=5295 + _globals['_APPROVALREQUEST']._serialized_end=5423 + _globals['_APPROVALRESPONSE']._serialized_start=5425 + _globals['_APPROVALRESPONSE']._serialized_end=5495 + _globals['_LISTMODELSRESPONSE']._serialized_start=5497 + _globals['_LISTMODELSRESPONSE']._serialized_end=5562 + _globals['_PARSETOOLCALLSRESPONSE']._serialized_start=5564 + _globals['_PARSETOOLCALLSRESPONSE']._serialized_end=5643 + _globals['_ORCHESTRATOREXECUTEREQUEST']._serialized_start=5645 + _globals['_ORCHESTRATOREXECUTEREQUEST']._serialized_end=5709 + _globals['_ORCHESTRATOREXECUTERESPONSE']._serialized_start=5711 + _globals['_ORCHESTRATOREXECUTERESPONSE']._serialized_end=5773 + _globals['_ADDMESSAGEREQUEST']._serialized_start=5775 + _globals['_ADDMESSAGEREQUEST']._serialized_end=5838 + _globals['_GETMESSAGESRESPONSE']._serialized_start=5840 + _globals['_GETMESSAGESRESPONSE']._serialized_end=5906 + _globals['_GETMESSAGESFORREQUESTPARAMS']._serialized_start=5908 + _globals['_GETMESSAGESFORREQUESTPARAMS']._serialized_end=5982 + _globals['_SETMESSAGESREQUEST']._serialized_start=5984 + _globals['_SETMESSAGESREQUEST']._serialized_end=6049 + _globals['_HOOKHANDLEREQUEST']._serialized_start=6051 + _globals['_HOOKHANDLEREQUEST']._serialized_end=6104 + _globals['_GETSUBSCRIPTIONSREQUEST']._serialized_start=6106 + _globals['_GETSUBSCRIPTIONSREQUEST']._serialized_end=6152 + _globals['_GETSUBSCRIPTIONSRESPONSE']._serialized_start=6154 + _globals['_GETSUBSCRIPTIONSRESPONSE']._serialized_end=6240 + _globals['_EVENTSUBSCRIPTION']._serialized_start=6242 + _globals['_EVENTSUBSCRIPTION']._serialized_end=6308 + _globals['_COMPLETEWITHPROVIDERREQUEST']._serialized_start=6310 + _globals['_COMPLETEWITHPROVIDERREQUEST']._serialized_end=6410 + _globals['_EXECUTETOOLREQUEST']._serialized_start=6412 + _globals['_EXECUTETOOLREQUEST']._serialized_end=6471 + _globals['_EMITHOOKREQUEST']._serialized_start=6473 + _globals['_EMITHOOKREQUEST']._serialized_end=6524 + _globals['_EMITHOOKANDCOLLECTREQUEST']._serialized_start=6526 + _globals['_EMITHOOKANDCOLLECTREQUEST']._serialized_end=6612 + _globals['_EMITHOOKANDCOLLECTRESPONSE']._serialized_start=6614 + _globals['_EMITHOOKANDCOLLECTRESPONSE']._serialized_end=6666 + _globals['_GETMESSAGESREQUEST']._serialized_start=6668 + _globals['_GETMESSAGESREQUEST']._serialized_end=6708 + _globals['_KERNELADDMESSAGEREQUEST']._serialized_start=6710 + _globals['_KERNELADDMESSAGEREQUEST']._serialized_end=6799 + _globals['_GETMOUNTEDMODULEREQUEST']._serialized_start=6801 + _globals['_GETMOUNTEDMODULEREQUEST']._serialized_end=6898 + _globals['_GETMOUNTEDMODULERESPONSE']._serialized_start=6900 + _globals['_GETMOUNTEDMODULERESPONSE']._serialized_end=6985 + _globals['_REGISTERCAPABILITYREQUEST']._serialized_start=6987 + _globals['_REGISTERCAPABILITYREQUEST']._serialized_end=7048 + _globals['_GETCAPABILITYREQUEST']._serialized_start=7050 + _globals['_GETCAPABILITYREQUEST']._serialized_end=7086 + _globals['_GETCAPABILITYRESPONSE']._serialized_start=7088 + _globals['_GETCAPABILITYRESPONSE']._serialized_end=7146 + _globals['_TOOLSERVICE']._serialized_start=9135 + _globals['_TOOLSERVICE']._serialized_end=9300 + _globals['_PROVIDERSERVICE']._serialized_start=9303 + _globals['_PROVIDERSERVICE']._serialized_end=9718 + _globals['_ORCHESTRATORSERVICE']._serialized_start=9720 + _globals['_ORCHESTRATORSERVICE']._serialized_end=9845 + _globals['_CONTEXTSERVICE']._serialized_start=9848 + _globals['_CONTEXTSERVICE']._serialized_end=10267 + _globals['_HOOKSERVICE']._serialized_start=10270 + _globals['_HOOKSERVICE']._serialized_end=10467 + _globals['_APPROVALSERVICE']._serialized_start=10469 + _globals['_APPROVALSERVICE']._serialized_end=10576 + _globals['_KERNELSERVICE']._serialized_start=10579 + _globals['_KERNELSERVICE']._serialized_end=11555 + _globals['_MODULELIFECYCLE']._serialized_start=11558 + _globals['_MODULELIFECYCLE']._serialized_end=11861 # @@protoc_insertion_point(module_scope) diff --git a/proto/test_task03_module_specific.py b/proto/test_task03_module_specific.py index 80c7b8b6..3c0fc2e3 100644 --- a/proto/test_task03_module_specific.py +++ b/proto/test_task03_module_specific.py @@ -222,6 +222,27 @@ def test_approval_response_message(): assert field_present(body, field), f"ApprovalResponse missing field: {field}" + + +def test_usage_message_has_cost_usd(): + """Usage message must have cost_usd as optional string field 7. + + String type matches Decimal JSON serialization on the Python/SessionStatus side. + None means unknown cost (not zero). + """ + content = read_proto() + assert "message Usage" in content, "Missing message Usage" + m = re.search(r'message Usage\s*\{([^}]+)\}', content) + assert m, "Cannot parse Usage body" + body = m.group(1) + assert "cost_usd" in body, ( + "Usage message missing field cost_usd. " + "Add: optional string cost_usd = 7; // Decimal as string; None = unknown cost" + ) + assert field_present(body, "string cost_usd"), ( + f"cost_usd should be type 'string' (Decimal serializes as string), got: {body}" + ) + if __name__ == "__main__": # Run all test functions failed = [] From 70421893823012338e3ef0cad36608026bae8287 Mon Sep 17 00:00:00 2001 From: Ken Chau Date: Mon, 4 May 2026 15:10:44 -0700 Subject: [PATCH 06/11] fix: add cost_usd field to generated Usage conversions and equivalence test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The proto Usage message gained cost_usd: Option in amplifier.module.rs, but the generated conversion and test files were not updated. - conversions.rs: set cost_usd: None when converting messages::Usage → proto Usage (messages::Usage has no cost_usd field; cost is tracked at session level) - equivalence_tests.rs: add cost_usd: Some("0.001234".into()) to the proto_usage_has_all_token_fields test and corresponding assertion Fixes Rust compilation error: E0063 missing field cost_usd --- crates/amplifier-core/src/generated/conversions.rs | 1 + crates/amplifier-core/src/generated/equivalence_tests.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/crates/amplifier-core/src/generated/conversions.rs b/crates/amplifier-core/src/generated/conversions.rs index 39b06cfa..bd6d2fe3 100644 --- a/crates/amplifier-core/src/generated/conversions.rs +++ b/crates/amplifier-core/src/generated/conversions.rs @@ -168,6 +168,7 @@ impl From for super::amplifier_module::Usage { i32::MAX }) }), + cost_usd: None, } } } diff --git a/crates/amplifier-core/src/generated/equivalence_tests.rs b/crates/amplifier-core/src/generated/equivalence_tests.rs index 87b4775f..59754f85 100644 --- a/crates/amplifier-core/src/generated/equivalence_tests.rs +++ b/crates/amplifier-core/src/generated/equivalence_tests.rs @@ -176,6 +176,7 @@ mod tests { reasoning_tokens: Some(20), cache_read_tokens: Some(30), cache_creation_tokens: Some(10), + cost_usd: Some("0.001234".into()), }; assert_eq!(usage.prompt_tokens, 100); assert_eq!(usage.completion_tokens, 50); @@ -183,6 +184,7 @@ mod tests { assert_eq!(usage.reasoning_tokens, Some(20)); assert_eq!(usage.cache_read_tokens, Some(30)); assert_eq!(usage.cache_creation_tokens, Some(10)); + assert_eq!(usage.cost_usd, Some("0.001234".to_string())); } #[test] From 8c0f4c80edffff44aeb1337b27674483ae7dcbfd Mon Sep 17 00:00:00 2001 From: Ken Chau Date: Mon, 4 May 2026 15:14:09 -0700 Subject: [PATCH 07/11] chore: bump version to 1.4.0 for M1 cost_usd fields --- bindings/python/Cargo.toml | 2 +- crates/amplifier-core/Cargo.toml | 2 +- crates/amplifier-core/src/generated/amplifier.module.rs | 5 ++++- pyproject.toml | 2 +- python/amplifier_core/__init__.py | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index 01a0059e..b43bb851 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "amplifier-core-py" -version = "1.4.1" +version = "1.4.0" edition = "2021" description = "PyO3 bridge for amplifier-core Rust kernel" license = "MIT" diff --git a/crates/amplifier-core/Cargo.toml b/crates/amplifier-core/Cargo.toml index ba61d61a..b0521241 100644 --- a/crates/amplifier-core/Cargo.toml +++ b/crates/amplifier-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "amplifier-core" -version = "1.4.1" +version = "1.4.0" edition = "2021" description = "Pure Rust kernel for the Amplifier modular AI agent system" license = "MIT" diff --git a/crates/amplifier-core/src/generated/amplifier.module.rs b/crates/amplifier-core/src/generated/amplifier.module.rs index d510a11f..75ccefa4 100644 --- a/crates/amplifier-core/src/generated/amplifier.module.rs +++ b/crates/amplifier-core/src/generated/amplifier.module.rs @@ -318,7 +318,7 @@ pub mod response_format { JsonSchema(super::JsonSchemaFormat), } } -#[derive(Clone, Copy, PartialEq, ::prost::Message)] +#[derive(Clone, PartialEq, ::prost::Message)] pub struct Usage { #[prost(int32, tag = "1")] pub prompt_tokens: i32, @@ -332,6 +332,9 @@ pub struct Usage { pub cache_read_tokens: ::core::option::Option, #[prost(int32, optional, tag = "6")] pub cache_creation_tokens: ::core::option::Option, + /// Decimal as string; None = unknown cost + #[prost(string, optional, tag = "7")] + pub cost_usd: ::core::option::Option<::prost::alloc::string::String>, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Degradation { diff --git a/pyproject.toml b/pyproject.toml index 30bcf957..550e2e22 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "amplifier-core" -version = "1.4.1" +version = "1.4.0" description = "Rust kernel with Python bindings for the Amplifier modular AI agent framework" license = "MIT" readme = "README.md" diff --git a/python/amplifier_core/__init__.py b/python/amplifier_core/__init__.py index 4e80cd3e..700e4d37 100644 --- a/python/amplifier_core/__init__.py +++ b/python/amplifier_core/__init__.py @@ -6,7 +6,7 @@ AmplifierSession`) still give the pure-Python implementations. """ -__version__ = "1.0.7" +__version__ = "1.4.0" # --- Rust-backed primary types (THE SWITCHOVER) --- # These four were previously imported from their Python submodules. From 1a5d801f142b2f11a245fd16d450ac5fbe8746e8 Mon Sep 17 00:00:00 2001 From: Ken Chau Date: Mon, 4 May 2026 20:56:03 -0700 Subject: [PATCH 08/11] =?UTF-8?q?fix:=20address=20COE=20review=20=E2=80=94?= =?UTF-8?q?=20remove=20estimated=5Fcost,=20fix=20proto=20conversion,=20bum?= =?UTF-8?q?p=201.5.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove estimated_cost: float from SessionStatus (Python + Rust) — was never populated, removal was always the plan per M1 design - Fix proto cost_usd field: messages::Usage has no cost_usd, so removed optional string cost_usd = 7 from proto entirely; regenerated pb2.py and amplifier.module.rs (prost also added Copy derive to Usage now all fields are Copy-safe) - Remove cost_usd: None from conversions.rs From impl - Remove cost_usd references from equivalence_tests.rs - Delete proto/test_task03_module_specific.py (tested cost_usd field that no longer exists in proto) - Bump version to 1.5.0 (upstream was already at 1.4.1; 1.5.0 is correct next MINOR) - Add Field(description=...) to Usage.cost_usd in message_models.py for IDE/schema visibility - Add EOF newline to models.rs --- Cargo.lock | 4 +- bindings/python/Cargo.toml | 2 +- bindings/python/tests/test_cost_models.py | 5 - crates/amplifier-core/Cargo.toml | 2 +- .../src/generated/amplifier.module.rs | 5 +- .../src/generated/conversions.rs | 1 - .../src/generated/equivalence_tests.rs | 2 - crates/amplifier-core/src/models.rs | 8 +- proto/amplifier_module.proto | 1 - proto/amplifier_module_pb2.py | 222 +++++++-------- proto/test_task03_module_specific.py | 260 ------------------ pyproject.toml | 2 +- python/amplifier_core/__init__.py | 2 +- python/amplifier_core/message_models.py | 9 +- python/amplifier_core/models.py | 6 - uv.lock | 2 +- 16 files changed, 128 insertions(+), 405 deletions(-) delete mode 100644 proto/test_task03_module_specific.py diff --git a/Cargo.lock b/Cargo.lock index a4b85d7f..6194ab99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,7 +40,7 @@ checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" [[package]] name = "amplifier-core" -version = "1.4.1" +version = "1.5.0" dependencies = [ "chrono", "log", @@ -76,7 +76,7 @@ dependencies = [ [[package]] name = "amplifier-core-py" -version = "1.4.1" +version = "1.5.0" dependencies = [ "amplifier-core", "log", diff --git a/bindings/python/Cargo.toml b/bindings/python/Cargo.toml index b43bb851..fbe7aff0 100644 --- a/bindings/python/Cargo.toml +++ b/bindings/python/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "amplifier-core-py" -version = "1.4.0" +version = "1.5.0" edition = "2021" description = "PyO3 bridge for amplifier-core Rust kernel" license = "MIT" diff --git a/bindings/python/tests/test_cost_models.py b/bindings/python/tests/test_cost_models.py index 1db25357..003f2a6f 100644 --- a/bindings/python/tests/test_cost_models.py +++ b/bindings/python/tests/test_cost_models.py @@ -118,11 +118,6 @@ def test_cost_usd_rejects_float(self): with pytest.raises(ValidationError): SessionStatus(session_id="test-123", cost_usd=1.23) - def test_estimated_cost_deprecated_but_still_works(self): - """estimated_cost still accepts float for backward compat (deprecated, not removed).""" - status = SessionStatus(session_id="test-123", estimated_cost=0.5) - assert status.estimated_cost == 0.5 - def test_to_dict_includes_cost_usd_as_string(self): """to_dict() uses mode='json' — cost_usd should serialize as string.""" status = SessionStatus(session_id="test-123", cost_usd=Decimal("2.50")) diff --git a/crates/amplifier-core/Cargo.toml b/crates/amplifier-core/Cargo.toml index b0521241..2a9bf44f 100644 --- a/crates/amplifier-core/Cargo.toml +++ b/crates/amplifier-core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "amplifier-core" -version = "1.4.0" +version = "1.5.0" edition = "2021" description = "Pure Rust kernel for the Amplifier modular AI agent system" license = "MIT" diff --git a/crates/amplifier-core/src/generated/amplifier.module.rs b/crates/amplifier-core/src/generated/amplifier.module.rs index 75ccefa4..d510a11f 100644 --- a/crates/amplifier-core/src/generated/amplifier.module.rs +++ b/crates/amplifier-core/src/generated/amplifier.module.rs @@ -318,7 +318,7 @@ pub mod response_format { JsonSchema(super::JsonSchemaFormat), } } -#[derive(Clone, PartialEq, ::prost::Message)] +#[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct Usage { #[prost(int32, tag = "1")] pub prompt_tokens: i32, @@ -332,9 +332,6 @@ pub struct Usage { pub cache_read_tokens: ::core::option::Option, #[prost(int32, optional, tag = "6")] pub cache_creation_tokens: ::core::option::Option, - /// Decimal as string; None = unknown cost - #[prost(string, optional, tag = "7")] - pub cost_usd: ::core::option::Option<::prost::alloc::string::String>, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct Degradation { diff --git a/crates/amplifier-core/src/generated/conversions.rs b/crates/amplifier-core/src/generated/conversions.rs index bd6d2fe3..39b06cfa 100644 --- a/crates/amplifier-core/src/generated/conversions.rs +++ b/crates/amplifier-core/src/generated/conversions.rs @@ -168,7 +168,6 @@ impl From for super::amplifier_module::Usage { i32::MAX }) }), - cost_usd: None, } } } diff --git a/crates/amplifier-core/src/generated/equivalence_tests.rs b/crates/amplifier-core/src/generated/equivalence_tests.rs index 59754f85..87b4775f 100644 --- a/crates/amplifier-core/src/generated/equivalence_tests.rs +++ b/crates/amplifier-core/src/generated/equivalence_tests.rs @@ -176,7 +176,6 @@ mod tests { reasoning_tokens: Some(20), cache_read_tokens: Some(30), cache_creation_tokens: Some(10), - cost_usd: Some("0.001234".into()), }; assert_eq!(usage.prompt_tokens, 100); assert_eq!(usage.completion_tokens, 50); @@ -184,7 +183,6 @@ mod tests { assert_eq!(usage.reasoning_tokens, Some(20)); assert_eq!(usage.cache_read_tokens, Some(30)); assert_eq!(usage.cache_creation_tokens, Some(10)); - assert_eq!(usage.cost_usd, Some("0.001234".to_string())); } #[test] diff --git a/crates/amplifier-core/src/models.rs b/crates/amplifier-core/src/models.rs index 03474d60..5b5c6429 100644 --- a/crates/amplifier-core/src/models.rs +++ b/crates/amplifier-core/src/models.rs @@ -456,10 +456,6 @@ pub struct SessionStatus { #[serde(default, skip_serializing_if = "Option::is_none")] pub cost_usd: Option, - /// Deprecated: use cost_usd. Retained for backward compatibility. - #[serde(default)] - pub estimated_cost: Option, - // Last activity /// Last activity timestamp (ISO 8601 string). #[serde(default)] @@ -872,7 +868,6 @@ mod tests { total_input_tokens: 1000, total_output_tokens: 500, cost_usd: None, - estimated_cost: Some(0.05), last_activity: Some("2025-01-01T00:01:00Z".into()), last_error: None, }; @@ -881,7 +876,6 @@ mod tests { assert_eq!(deserialized.session_id, "sess-123"); assert_eq!(deserialized.status, SessionState::Running); assert_eq!(deserialized.total_messages, 5); - assert_eq!(deserialized.estimated_cost, Some(0.05)); } #[test] @@ -906,4 +900,4 @@ mod tests { let status_no_cost: SessionStatus = serde_json::from_str(json_no_cost).unwrap(); assert!(status_no_cost.cost_usd.is_none()); } -} \ No newline at end of file +} diff --git a/proto/amplifier_module.proto b/proto/amplifier_module.proto index ca65a007..e12f988a 100644 --- a/proto/amplifier_module.proto +++ b/proto/amplifier_module.proto @@ -305,7 +305,6 @@ message Usage { optional int32 reasoning_tokens = 4; optional int32 cache_read_tokens = 5; optional int32 cache_creation_tokens = 6; - optional string cost_usd = 7; // Decimal as string; None = unknown cost } message Degradation { diff --git a/proto/amplifier_module_pb2.py b/proto/amplifier_module_pb2.py index c43ce6a0..d4acf8db 100644 --- a/proto/amplifier_module_pb2.py +++ b/proto/amplifier_module_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: amplifier_module.proto -# Protobuf Python Version: 6.31.1 +# Protobuf Python Version: 6.33.2 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -12,8 +12,8 @@ _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, 6, - 31, - 1, + 33, + 2, '', 'amplifier_module.proto' ) @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x61mplifier_module.proto\x12\x10\x61mplifier.module\"\x07\n\x05\x45mpty\"F\n\x08ToolSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x17\n\x0fparameters_json\x18\x03 \x01(\t\"9\n\x12ToolExecuteRequest\x12\r\n\x05input\x18\x01 \x01(\x0c\x12\x14\n\x0c\x63ontent_type\x18\x02 \x01(\t\"[\n\x13ToolExecuteResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0e\n\x06output\x18\x02 \x01(\x0c\x12\x14\n\x0c\x63ontent_type\x18\x03 \x01(\t\x12\r\n\x05\x65rror\x18\x04 \x01(\t\"\xd6\x01\n\nModuleInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t\x12\x31\n\x0bmodule_type\x18\x04 \x01(\x0e\x32\x1c.amplifier.module.ModuleType\x12\x13\n\x0bmount_point\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t\x12\x1a\n\x12\x63onfig_schema_json\x18\x07 \x01(\t\x12\x14\n\x0c\x63\x61pabilities\x18\x08 \x03(\t\x12\x0e\n\x06\x61uthor\x18\t \x01(\t\"\x8c\x01\n\x0cMountRequest\x12:\n\x06\x63onfig\x18\x01 \x03(\x0b\x32*.amplifier.module.MountRequest.ConfigEntry\x12\x11\n\tmodule_id\x18\x02 \x01(\t\x1a-\n\x0b\x43onfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"_\n\rMountResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12.\n\x06status\x18\x03 \x01(\x0e\x32\x1e.amplifier.module.HealthStatus\"V\n\x13HealthCheckResponse\x12.\n\x06status\x18\x01 \x01(\x0e\x32\x1e.amplifier.module.HealthStatus\x12\x0f\n\x07message\x18\x02 \x01(\t\"\xca\x02\n\x0b\x43onfigField\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x35\n\nfield_type\x18\x03 \x01(\x0e\x32!.amplifier.module.ConfigFieldType\x12\x0e\n\x06prompt\x18\x04 \x01(\t\x12\x0f\n\x07\x65nv_var\x18\x05 \x01(\t\x12\x0f\n\x07\x63hoices\x18\x06 \x03(\t\x12\x10\n\x08required\x18\x07 \x01(\x08\x12\x15\n\rdefault_value\x18\x08 \x01(\t\x12>\n\tshow_when\x18\t \x03(\x0b\x32+.amplifier.module.ConfigField.ShowWhenEntry\x12\x16\n\x0erequires_model\x18\n \x01(\x08\x1a/\n\rShowWhenEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xbc\x01\n\rProviderError\x12\x37\n\nerror_type\x18\x01 \x01(\x0e\x32#.amplifier.module.ProviderErrorType\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x15\n\rprovider_name\x18\x03 \x01(\t\x12\r\n\x05model\x18\x04 \x01(\t\x12\x13\n\x0bstatus_code\x18\x05 \x01(\x05\x12\x11\n\tretryable\x18\x06 \x01(\x08\x12\x13\n\x0bretry_after\x18\x07 \x01(\x01\"\x97\x01\n\tToolError\x12\x33\n\nerror_type\x18\x01 \x01(\x0e\x32\x1f.amplifier.module.ToolErrorType\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x11\n\ttool_name\x18\x03 \x01(\t\x12\x0e\n\x06stdout\x18\x04 \x01(\t\x12\x0e\n\x06stderr\x18\x05 \x01(\t\x12\x11\n\texit_code\x18\x06 \x01(\x05\"d\n\tHookError\x12\x33\n\nerror_type\x18\x01 \x01(\x0e\x32\x1f.amplifier.module.HookErrorType\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x11\n\thook_name\x18\x03 \x01(\t\"\xef\x01\n\x0e\x41mplifierError\x12\x39\n\x0eprovider_error\x18\x01 \x01(\x0b\x32\x1f.amplifier.module.ProviderErrorH\x00\x12\x31\n\ntool_error\x18\x02 \x01(\x0b\x32\x1b.amplifier.module.ToolErrorH\x00\x12\x31\n\nhook_error\x18\x03 \x01(\x0b\x32\x1b.amplifier.module.HookErrorH\x00\x12\x17\n\rgeneric_error\x18\x04 \x01(\tH\x00\x12\x1a\n\x10validation_error\x18\x05 \x01(\tH\x00\x42\x07\n\x05\x65rror\"\x19\n\tTextBlock\x12\x0c\n\x04text\x18\x01 \x01(\t\"E\n\rThinkingBlock\x12\x10\n\x08thinking\x18\x01 \x01(\t\x12\x11\n\tsignature\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\"%\n\x15RedactedThinkingBlock\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\t\"=\n\rToolCallBlock\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x12\n\ninput_json\x18\x03 \x01(\t\"<\n\x0fToolResultBlock\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x13\n\x0boutput_json\x18\x02 \x01(\t\"C\n\nImageBlock\x12\x12\n\nmedia_type\x18\x01 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\x13\n\x0bsource_json\x18\x03 \x01(\t\"2\n\x0eReasoningBlock\x12\x0f\n\x07\x63ontent\x18\x01 \x03(\t\x12\x0f\n\x07summary\x18\x02 \x03(\t\"\xf1\x03\n\x0c\x43ontentBlock\x12\x31\n\ntext_block\x18\x01 \x01(\x0b\x32\x1b.amplifier.module.TextBlockH\x00\x12\x39\n\x0ethinking_block\x18\x02 \x01(\x0b\x32\x1f.amplifier.module.ThinkingBlockH\x00\x12J\n\x17redacted_thinking_block\x18\x03 \x01(\x0b\x32\'.amplifier.module.RedactedThinkingBlockH\x00\x12:\n\x0ftool_call_block\x18\x04 \x01(\x0b\x32\x1f.amplifier.module.ToolCallBlockH\x00\x12>\n\x11tool_result_block\x18\x05 \x01(\x0b\x32!.amplifier.module.ToolResultBlockH\x00\x12\x33\n\x0bimage_block\x18\x06 \x01(\x0b\x32\x1c.amplifier.module.ImageBlockH\x00\x12;\n\x0freasoning_block\x18\x07 \x01(\x0b\x32 .amplifier.module.ReasoningBlockH\x00\x12\x30\n\nvisibility\x18\x08 \x01(\x0e\x32\x1c.amplifier.module.VisibilityB\x07\n\x05\x62lock\"B\n\x10\x43ontentBlockList\x12.\n\x06\x62locks\x18\x01 \x03(\x0b\x32\x1e.amplifier.module.ContentBlock\"\xca\x01\n\x07Message\x12$\n\x04role\x18\x01 \x01(\x0e\x32\x16.amplifier.module.Role\x12\x16\n\x0ctext_content\x18\x02 \x01(\tH\x00\x12;\n\rblock_content\x18\x03 \x01(\x0b\x32\".amplifier.module.ContentBlockListH\x00\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x14\n\x0ctool_call_id\x18\x05 \x01(\t\x12\x15\n\rmetadata_json\x18\x06 \x01(\tB\t\n\x07\x63ontent\"C\n\x0fToolCallMessage\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"K\n\rToolSpecProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x17\n\x0fparameters_json\x18\x03 \x01(\t\"7\n\x10JsonSchemaFormat\x12\x13\n\x0bschema_json\x18\x01 \x01(\t\x12\x0e\n\x06strict\x18\x02 \x01(\x08\"u\n\x0eResponseFormat\x12\x0e\n\x04text\x18\x01 \x01(\x08H\x00\x12\x0e\n\x04json\x18\x02 \x01(\x08H\x00\x12\x39\n\x0bjson_schema\x18\x03 \x01(\x0b\x32\".amplifier.module.JsonSchemaFormatH\x00\x42\x08\n\x06\x66ormat\"\x9b\x02\n\x05Usage\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\x12\x1d\n\x10reasoning_tokens\x18\x04 \x01(\x05H\x00\x88\x01\x01\x12\x1e\n\x11\x63\x61\x63he_read_tokens\x18\x05 \x01(\x05H\x01\x88\x01\x01\x12\"\n\x15\x63\x61\x63he_creation_tokens\x18\x06 \x01(\x05H\x02\x88\x01\x01\x12\x15\n\x08\x63ost_usd\x18\x07 \x01(\tH\x03\x88\x01\x01\x42\x13\n\x11_reasoning_tokensB\x14\n\x12_cache_read_tokensB\x18\n\x16_cache_creation_tokensB\x0b\n\t_cost_usd\"@\n\x0b\x44\x65gradation\x12\x11\n\trequested\x18\x01 \x01(\t\x12\x0e\n\x06\x61\x63tual\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\"\x81\x03\n\x0b\x43hatRequest\x12+\n\x08messages\x18\x01 \x03(\x0b\x32\x19.amplifier.module.Message\x12.\n\x05tools\x18\x02 \x03(\x0b\x32\x1f.amplifier.module.ToolSpecProto\x12\x39\n\x0fresponse_format\x18\x03 \x01(\x0b\x32 .amplifier.module.ResponseFormat\x12\x13\n\x0btemperature\x18\x04 \x01(\x01\x12\r\n\x05top_p\x18\x05 \x01(\x01\x12\x19\n\x11max_output_tokens\x18\x06 \x01(\x05\x12\x17\n\x0f\x63onversation_id\x18\x07 \x01(\t\x12\x0e\n\x06stream\x18\x08 \x01(\x08\x12\x15\n\rmetadata_json\x18\t \x01(\t\x12\r\n\x05model\x18\n \x01(\t\x12\x13\n\x0btool_choice\x18\x0b \x01(\t\x12\x0c\n\x04stop\x18\x0c \x03(\t\x12\x18\n\x10reasoning_effort\x18\r \x01(\t\x12\x0f\n\x07timeout\x18\x0e \x01(\x01\"\x98\x02\n\x0c\x43hatResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x35\n\ntool_calls\x18\x02 \x03(\x0b\x32!.amplifier.module.ToolCallMessage\x12&\n\x05usage\x18\x03 \x01(\x0b\x32\x17.amplifier.module.Usage\x12\x32\n\x0b\x64\x65gradation\x18\x04 \x01(\x0b\x32\x1d.amplifier.module.Degradation\x12\x15\n\rfinish_reason\x18\x05 \x01(\t\x12\x15\n\rmetadata_json\x18\x06 \x01(\t\x12\x36\n\x0e\x63ontent_blocks\x18\x07 \x03(\x0b\x32\x1e.amplifier.module.ContentBlock\"F\n\nToolResult\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x13\n\x0boutput_json\x18\x02 \x01(\t\x12\x12\n\nerror_json\x18\x03 \x01(\t\"\xa7\x04\n\nHookResult\x12,\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\x1c.amplifier.module.HookAction\x12\x11\n\tdata_json\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x19\n\x11\x63ontext_injection\x18\x04 \x01(\t\x12\x46\n\x16\x63ontext_injection_role\x18\x05 \x01(\x0e\x32&.amplifier.module.ContextInjectionRole\x12\x11\n\tephemeral\x18\x06 \x01(\x08\x12\x17\n\x0f\x61pproval_prompt\x18\x07 \x01(\t\x12\x18\n\x10\x61pproval_options\x18\x08 \x03(\t\x12\x1d\n\x10\x61pproval_timeout\x18\t \x01(\x01H\x00\x88\x01\x01\x12;\n\x10\x61pproval_default\x18\n \x01(\x0e\x32!.amplifier.module.ApprovalDefault\x12\x17\n\x0fsuppress_output\x18\x0b \x01(\x08\x12\x14\n\x0cuser_message\x18\x0c \x01(\t\x12>\n\x12user_message_level\x18\r \x01(\x0e\x32\".amplifier.module.UserMessageLevel\x12\x1b\n\x13user_message_source\x18\x0e \x01(\t\x12\"\n\x1a\x61ppend_to_last_tool_result\x18\x0f \x01(\x08\x42\x13\n\x11_approval_timeout\"\x8d\x01\n\tModelInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x16\n\x0e\x63ontext_window\x18\x03 \x01(\x05\x12\x19\n\x11max_output_tokens\x18\x04 \x01(\x05\x12\x14\n\x0c\x63\x61pabilities\x18\x05 \x03(\t\x12\x15\n\rdefaults_json\x18\x06 \x01(\t\"\xb0\x01\n\x0cProviderInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x1b\n\x13\x63redential_env_vars\x18\x03 \x03(\t\x12\x14\n\x0c\x63\x61pabilities\x18\x04 \x03(\t\x12\x15\n\rdefaults_json\x18\x05 \x01(\t\x12\x34\n\rconfig_fields\x18\x06 \x03(\x0b\x32\x1d.amplifier.module.ConfigField\"\x80\x01\n\x0f\x41pprovalRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x0e\n\x06\x61\x63tion\x18\x02 \x01(\t\x12\x14\n\x0c\x64\x65tails_json\x18\x03 \x01(\t\x12\x12\n\nrisk_level\x18\x04 \x01(\t\x12\x14\n\x07timeout\x18\x05 \x01(\x01H\x00\x88\x01\x01\x42\n\n\x08_timeout\"F\n\x10\x41pprovalResponse\x12\x10\n\x08\x61pproved\x18\x01 \x01(\x08\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x10\n\x08remember\x18\x03 \x01(\x08\"A\n\x12ListModelsResponse\x12+\n\x06models\x18\x01 \x03(\x0b\x32\x1b.amplifier.module.ModelInfo\"O\n\x16ParseToolCallsResponse\x12\x35\n\ntool_calls\x18\x01 \x03(\x0b\x32!.amplifier.module.ToolCallMessage\"@\n\x1aOrchestratorExecuteRequest\x12\x0e\n\x06prompt\x18\x01 \x01(\t\x12\x12\n\nsession_id\x18\x02 \x01(\t\">\n\x1bOrchestratorExecuteResponse\x12\x10\n\x08response\x18\x01 \x01(\t\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"?\n\x11\x41\x64\x64MessageRequest\x12*\n\x07message\x18\x01 \x01(\x0b\x32\x19.amplifier.module.Message\"B\n\x13GetMessagesResponse\x12+\n\x08messages\x18\x01 \x03(\x0b\x32\x19.amplifier.module.Message\"J\n\x1bGetMessagesForRequestParams\x12\x14\n\x0ctoken_budget\x18\x01 \x01(\x05\x12\x15\n\rprovider_name\x18\x02 \x01(\t\"A\n\x12SetMessagesRequest\x12+\n\x08messages\x18\x01 \x03(\x0b\x32\x19.amplifier.module.Message\"5\n\x11HookHandleRequest\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\tdata_json\x18\x02 \x01(\t\".\n\x17GetSubscriptionsRequest\x12\x13\n\x0b\x63onfig_json\x18\x01 \x01(\t\"V\n\x18GetSubscriptionsResponse\x12:\n\rsubscriptions\x18\x01 \x03(\x0b\x32#.amplifier.module.EventSubscription\"B\n\x11\x45ventSubscription\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x10\n\x08priority\x18\x02 \x01(\x05\x12\x0c\n\x04name\x18\x03 \x01(\t\"d\n\x1b\x43ompleteWithProviderRequest\x12\x15\n\rprovider_name\x18\x01 \x01(\t\x12.\n\x07request\x18\x02 \x01(\x0b\x32\x1d.amplifier.module.ChatRequest\";\n\x12\x45xecuteToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x12\n\ninput_json\x18\x02 \x01(\t\"3\n\x0f\x45mitHookRequest\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\tdata_json\x18\x02 \x01(\t\"V\n\x19\x45mitHookAndCollectRequest\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\tdata_json\x18\x02 \x01(\t\x12\x17\n\x0ftimeout_seconds\x18\x03 \x01(\x01\"4\n\x1a\x45mitHookAndCollectResponse\x12\x16\n\x0eresponses_json\x18\x01 \x03(\t\"(\n\x12GetMessagesRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"Y\n\x17KernelAddMessageRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12*\n\x07message\x18\x02 \x01(\x0b\x32\x19.amplifier.module.Message\"a\n\x17GetMountedModuleRequest\x12\x13\n\x0bmodule_name\x18\x01 \x01(\t\x12\x31\n\x0bmodule_type\x18\x02 \x01(\x0e\x32\x1c.amplifier.module.ModuleType\"U\n\x18GetMountedModuleResponse\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12*\n\x04info\x18\x02 \x01(\x0b\x32\x1c.amplifier.module.ModuleInfo\"=\n\x19RegisterCapabilityRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\nvalue_json\x18\x02 \x01(\t\"$\n\x14GetCapabilityRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\":\n\x15GetCapabilityResponse\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x12\n\nvalue_json\x18\x02 \x01(\t*\xbc\x01\n\nModuleType\x12\x1b\n\x17MODULE_TYPE_UNSPECIFIED\x10\x00\x12\x18\n\x14MODULE_TYPE_PROVIDER\x10\x01\x12\x14\n\x10MODULE_TYPE_TOOL\x10\x02\x12\x14\n\x10MODULE_TYPE_HOOK\x10\x03\x12\x16\n\x12MODULE_TYPE_MEMORY\x10\x04\x12\x19\n\x15MODULE_TYPE_GUARDRAIL\x10\x05\x12\x18\n\x14MODULE_TYPE_APPROVAL\x10\x06*\x82\x01\n\x0cHealthStatus\x12\x1d\n\x19HEALTH_STATUS_UNSPECIFIED\x10\x00\x12\x19\n\x15HEALTH_STATUS_SERVING\x10\x01\x12\x1d\n\x19HEALTH_STATUS_NOT_SERVING\x10\x02\x12\x19\n\x15HEALTH_STATUS_UNKNOWN\x10\x03*\xad\x01\n\x0f\x43onfigFieldType\x12!\n\x1d\x43ONFIG_FIELD_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x43ONFIG_FIELD_TYPE_STRING\x10\x01\x12\x1c\n\x18\x43ONFIG_FIELD_TYPE_NUMBER\x10\x02\x12\x1d\n\x19\x43ONFIG_FIELD_TYPE_BOOLEAN\x10\x03\x12\x1c\n\x18\x43ONFIG_FIELD_TYPE_SECRET\x10\x04*\xd8\x02\n\x11ProviderErrorType\x12#\n\x1fPROVIDER_ERROR_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18PROVIDER_ERROR_TYPE_AUTH\x10\x01\x12\"\n\x1ePROVIDER_ERROR_TYPE_RATE_LIMIT\x10\x02\x12&\n\"PROVIDER_ERROR_TYPE_CONTEXT_LENGTH\x10\x03\x12\'\n#PROVIDER_ERROR_TYPE_INVALID_REQUEST\x10\x04\x12&\n\"PROVIDER_ERROR_TYPE_CONTENT_FILTER\x10\x05\x12#\n\x1fPROVIDER_ERROR_TYPE_UNAVAILABLE\x10\x06\x12\x1f\n\x1bPROVIDER_ERROR_TYPE_TIMEOUT\x10\x07\x12\x1d\n\x19PROVIDER_ERROR_TYPE_OTHER\x10\x08*\x8c\x01\n\rToolErrorType\x12\x1f\n\x1bTOOL_ERROR_TYPE_UNSPECIFIED\x10\x00\x12\x1d\n\x19TOOL_ERROR_TYPE_EXECUTION\x10\x01\x12\x1e\n\x1aTOOL_ERROR_TYPE_VALIDATION\x10\x02\x12\x1b\n\x17TOOL_ERROR_TYPE_TIMEOUT\x10\x03*\x8c\x01\n\rHookErrorType\x12\x1f\n\x1bHOOK_ERROR_TYPE_UNSPECIFIED\x10\x00\x12\x1d\n\x19HOOK_ERROR_TYPE_EXECUTION\x10\x01\x12\x1e\n\x1aHOOK_ERROR_TYPE_VALIDATION\x10\x02\x12\x1b\n\x17HOOK_ERROR_TYPE_TIMEOUT\x10\x03*\x86\x01\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04\x12\x11\n\rROLE_FUNCTION\x10\x05\x12\x12\n\x0eROLE_DEVELOPER\x10\x06*o\n\nVisibility\x12\x1a\n\x16VISIBILITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eVISIBILITY_ALL\x10\x01\x12\x17\n\x13VISIBILITY_LLM_ONLY\x10\x02\x12\x18\n\x14VISIBILITY_USER_ONLY\x10\x03*\xab\x01\n\nHookAction\x12\x1b\n\x17HOOK_ACTION_UNSPECIFIED\x10\x00\x12\x18\n\x14HOOK_ACTION_CONTINUE\x10\x01\x12\x16\n\x12HOOK_ACTION_MODIFY\x10\x02\x12\x14\n\x10HOOK_ACTION_DENY\x10\x03\x12\x1e\n\x1aHOOK_ACTION_INJECT_CONTEXT\x10\x04\x12\x18\n\x14HOOK_ACTION_ASK_USER\x10\x05*\xa8\x01\n\x14\x43ontextInjectionRole\x12&\n\"CONTEXT_INJECTION_ROLE_UNSPECIFIED\x10\x00\x12!\n\x1d\x43ONTEXT_INJECTION_ROLE_SYSTEM\x10\x01\x12\x1f\n\x1b\x43ONTEXT_INJECTION_ROLE_USER\x10\x02\x12$\n CONTEXT_INJECTION_ROLE_ASSISTANT\x10\x03*l\n\x0f\x41pprovalDefault\x12 \n\x1c\x41PPROVAL_DEFAULT_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x41PPROVAL_DEFAULT_APPROVE\x10\x01\x12\x19\n\x15\x41PPROVAL_DEFAULT_DENY\x10\x02*\x91\x01\n\x10UserMessageLevel\x12\"\n\x1eUSER_MESSAGE_LEVEL_UNSPECIFIED\x10\x00\x12\x1b\n\x17USER_MESSAGE_LEVEL_INFO\x10\x01\x12\x1e\n\x1aUSER_MESSAGE_LEVEL_WARNING\x10\x02\x12\x1c\n\x18USER_MESSAGE_LEVEL_ERROR\x10\x03\x32\xa5\x01\n\x0bToolService\x12>\n\x07GetSpec\x12\x17.amplifier.module.Empty\x1a\x1a.amplifier.module.ToolSpec\x12V\n\x07\x45xecute\x12$.amplifier.module.ToolExecuteRequest\x1a%.amplifier.module.ToolExecuteResponse2\x9f\x03\n\x0fProviderService\x12\x42\n\x07GetInfo\x12\x17.amplifier.module.Empty\x1a\x1e.amplifier.module.ProviderInfo\x12K\n\nListModels\x12\x17.amplifier.module.Empty\x1a$.amplifier.module.ListModelsResponse\x12I\n\x08\x43omplete\x12\x1d.amplifier.module.ChatRequest\x1a\x1e.amplifier.module.ChatResponse\x12T\n\x11\x43ompleteStreaming\x12\x1d.amplifier.module.ChatRequest\x1a\x1e.amplifier.module.ChatResponse0\x01\x12Z\n\x0eParseToolCalls\x12\x1e.amplifier.module.ChatResponse\x1a(.amplifier.module.ParseToolCallsResponse2}\n\x13OrchestratorService\x12\x66\n\x07\x45xecute\x12,.amplifier.module.OrchestratorExecuteRequest\x1a-.amplifier.module.OrchestratorExecuteResponse2\xa3\x03\n\x0e\x43ontextService\x12J\n\nAddMessage\x12#.amplifier.module.AddMessageRequest\x1a\x17.amplifier.module.Empty\x12M\n\x0bGetMessages\x12\x17.amplifier.module.Empty\x1a%.amplifier.module.GetMessagesResponse\x12m\n\x15GetMessagesForRequest\x12-.amplifier.module.GetMessagesForRequestParams\x1a%.amplifier.module.GetMessagesResponse\x12L\n\x0bSetMessages\x12$.amplifier.module.SetMessagesRequest\x1a\x17.amplifier.module.Empty\x12\x39\n\x05\x43lear\x12\x17.amplifier.module.Empty\x1a\x17.amplifier.module.Empty2\xc5\x01\n\x0bHookService\x12K\n\x06Handle\x12#.amplifier.module.HookHandleRequest\x1a\x1c.amplifier.module.HookResult\x12i\n\x10GetSubscriptions\x12).amplifier.module.GetSubscriptionsRequest\x1a*.amplifier.module.GetSubscriptionsResponse2k\n\x0f\x41pprovalService\x12X\n\x0fRequestApproval\x12!.amplifier.module.ApprovalRequest\x1a\".amplifier.module.ApprovalResponse2\xd0\x07\n\rKernelService\x12\x65\n\x14\x43ompleteWithProvider\x12-.amplifier.module.CompleteWithProviderRequest\x1a\x1e.amplifier.module.ChatResponse\x12p\n\x1d\x43ompleteWithProviderStreaming\x12-.amplifier.module.CompleteWithProviderRequest\x1a\x1e.amplifier.module.ChatResponse0\x01\x12Q\n\x0b\x45xecuteTool\x12$.amplifier.module.ExecuteToolRequest\x1a\x1c.amplifier.module.ToolResult\x12K\n\x08\x45mitHook\x12!.amplifier.module.EmitHookRequest\x1a\x1c.amplifier.module.HookResult\x12o\n\x12\x45mitHookAndCollect\x12+.amplifier.module.EmitHookAndCollectRequest\x1a,.amplifier.module.EmitHookAndCollectResponse\x12Z\n\x0bGetMessages\x12$.amplifier.module.GetMessagesRequest\x1a%.amplifier.module.GetMessagesResponse\x12P\n\nAddMessage\x12).amplifier.module.KernelAddMessageRequest\x1a\x17.amplifier.module.Empty\x12i\n\x10GetMountedModule\x12).amplifier.module.GetMountedModuleRequest\x1a*.amplifier.module.GetMountedModuleResponse\x12Z\n\x12RegisterCapability\x12+.amplifier.module.RegisterCapabilityRequest\x1a\x17.amplifier.module.Empty\x12`\n\rGetCapability\x12&.amplifier.module.GetCapabilityRequest\x1a\'.amplifier.module.GetCapabilityResponse2\xaf\x02\n\x0fModuleLifecycle\x12H\n\x05Mount\x12\x1e.amplifier.module.MountRequest\x1a\x1f.amplifier.module.MountResponse\x12;\n\x07\x43leanup\x12\x17.amplifier.module.Empty\x1a\x17.amplifier.module.Empty\x12M\n\x0bHealthCheck\x12\x17.amplifier.module.Empty\x1a%.amplifier.module.HealthCheckResponse\x12\x46\n\rGetModuleInfo\x12\x17.amplifier.module.Empty\x1a\x1c.amplifier.module.ModuleInfob\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x61mplifier_module.proto\x12\x10\x61mplifier.module\"\x07\n\x05\x45mpty\"F\n\x08ToolSpec\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x17\n\x0fparameters_json\x18\x03 \x01(\t\"9\n\x12ToolExecuteRequest\x12\r\n\x05input\x18\x01 \x01(\x0c\x12\x14\n\x0c\x63ontent_type\x18\x02 \x01(\t\"[\n\x13ToolExecuteResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x0e\n\x06output\x18\x02 \x01(\x0c\x12\x14\n\x0c\x63ontent_type\x18\x03 \x01(\t\x12\r\n\x05\x65rror\x18\x04 \x01(\t\"\xd6\x01\n\nModuleInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07version\x18\x03 \x01(\t\x12\x31\n\x0bmodule_type\x18\x04 \x01(\x0e\x32\x1c.amplifier.module.ModuleType\x12\x13\n\x0bmount_point\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t\x12\x1a\n\x12\x63onfig_schema_json\x18\x07 \x01(\t\x12\x14\n\x0c\x63\x61pabilities\x18\x08 \x03(\t\x12\x0e\n\x06\x61uthor\x18\t \x01(\t\"\x8c\x01\n\x0cMountRequest\x12:\n\x06\x63onfig\x18\x01 \x03(\x0b\x32*.amplifier.module.MountRequest.ConfigEntry\x12\x11\n\tmodule_id\x18\x02 \x01(\t\x1a-\n\x0b\x43onfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"_\n\rMountResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12.\n\x06status\x18\x03 \x01(\x0e\x32\x1e.amplifier.module.HealthStatus\"V\n\x13HealthCheckResponse\x12.\n\x06status\x18\x01 \x01(\x0e\x32\x1e.amplifier.module.HealthStatus\x12\x0f\n\x07message\x18\x02 \x01(\t\"\xca\x02\n\x0b\x43onfigField\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x35\n\nfield_type\x18\x03 \x01(\x0e\x32!.amplifier.module.ConfigFieldType\x12\x0e\n\x06prompt\x18\x04 \x01(\t\x12\x0f\n\x07\x65nv_var\x18\x05 \x01(\t\x12\x0f\n\x07\x63hoices\x18\x06 \x03(\t\x12\x10\n\x08required\x18\x07 \x01(\x08\x12\x15\n\rdefault_value\x18\x08 \x01(\t\x12>\n\tshow_when\x18\t \x03(\x0b\x32+.amplifier.module.ConfigField.ShowWhenEntry\x12\x16\n\x0erequires_model\x18\n \x01(\x08\x1a/\n\rShowWhenEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xbc\x01\n\rProviderError\x12\x37\n\nerror_type\x18\x01 \x01(\x0e\x32#.amplifier.module.ProviderErrorType\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x15\n\rprovider_name\x18\x03 \x01(\t\x12\r\n\x05model\x18\x04 \x01(\t\x12\x13\n\x0bstatus_code\x18\x05 \x01(\x05\x12\x11\n\tretryable\x18\x06 \x01(\x08\x12\x13\n\x0bretry_after\x18\x07 \x01(\x01\"\x97\x01\n\tToolError\x12\x33\n\nerror_type\x18\x01 \x01(\x0e\x32\x1f.amplifier.module.ToolErrorType\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x11\n\ttool_name\x18\x03 \x01(\t\x12\x0e\n\x06stdout\x18\x04 \x01(\t\x12\x0e\n\x06stderr\x18\x05 \x01(\t\x12\x11\n\texit_code\x18\x06 \x01(\x05\"d\n\tHookError\x12\x33\n\nerror_type\x18\x01 \x01(\x0e\x32\x1f.amplifier.module.HookErrorType\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x11\n\thook_name\x18\x03 \x01(\t\"\xef\x01\n\x0e\x41mplifierError\x12\x39\n\x0eprovider_error\x18\x01 \x01(\x0b\x32\x1f.amplifier.module.ProviderErrorH\x00\x12\x31\n\ntool_error\x18\x02 \x01(\x0b\x32\x1b.amplifier.module.ToolErrorH\x00\x12\x31\n\nhook_error\x18\x03 \x01(\x0b\x32\x1b.amplifier.module.HookErrorH\x00\x12\x17\n\rgeneric_error\x18\x04 \x01(\tH\x00\x12\x1a\n\x10validation_error\x18\x05 \x01(\tH\x00\x42\x07\n\x05\x65rror\"\x19\n\tTextBlock\x12\x0c\n\x04text\x18\x01 \x01(\t\"E\n\rThinkingBlock\x12\x10\n\x08thinking\x18\x01 \x01(\t\x12\x11\n\tsignature\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\"%\n\x15RedactedThinkingBlock\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\t\"=\n\rToolCallBlock\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x12\n\ninput_json\x18\x03 \x01(\t\"<\n\x0fToolResultBlock\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x13\n\x0boutput_json\x18\x02 \x01(\t\"C\n\nImageBlock\x12\x12\n\nmedia_type\x18\x01 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\x12\x13\n\x0bsource_json\x18\x03 \x01(\t\"2\n\x0eReasoningBlock\x12\x0f\n\x07\x63ontent\x18\x01 \x03(\t\x12\x0f\n\x07summary\x18\x02 \x03(\t\"\xf1\x03\n\x0c\x43ontentBlock\x12\x31\n\ntext_block\x18\x01 \x01(\x0b\x32\x1b.amplifier.module.TextBlockH\x00\x12\x39\n\x0ethinking_block\x18\x02 \x01(\x0b\x32\x1f.amplifier.module.ThinkingBlockH\x00\x12J\n\x17redacted_thinking_block\x18\x03 \x01(\x0b\x32\'.amplifier.module.RedactedThinkingBlockH\x00\x12:\n\x0ftool_call_block\x18\x04 \x01(\x0b\x32\x1f.amplifier.module.ToolCallBlockH\x00\x12>\n\x11tool_result_block\x18\x05 \x01(\x0b\x32!.amplifier.module.ToolResultBlockH\x00\x12\x33\n\x0bimage_block\x18\x06 \x01(\x0b\x32\x1c.amplifier.module.ImageBlockH\x00\x12;\n\x0freasoning_block\x18\x07 \x01(\x0b\x32 .amplifier.module.ReasoningBlockH\x00\x12\x30\n\nvisibility\x18\x08 \x01(\x0e\x32\x1c.amplifier.module.VisibilityB\x07\n\x05\x62lock\"B\n\x10\x43ontentBlockList\x12.\n\x06\x62locks\x18\x01 \x03(\x0b\x32\x1e.amplifier.module.ContentBlock\"\xca\x01\n\x07Message\x12$\n\x04role\x18\x01 \x01(\x0e\x32\x16.amplifier.module.Role\x12\x16\n\x0ctext_content\x18\x02 \x01(\tH\x00\x12;\n\rblock_content\x18\x03 \x01(\x0b\x32\".amplifier.module.ContentBlockListH\x00\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x14\n\x0ctool_call_id\x18\x05 \x01(\t\x12\x15\n\rmetadata_json\x18\x06 \x01(\tB\t\n\x07\x63ontent\"C\n\x0fToolCallMessage\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"K\n\rToolSpecProto\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x17\n\x0fparameters_json\x18\x03 \x01(\t\"7\n\x10JsonSchemaFormat\x12\x13\n\x0bschema_json\x18\x01 \x01(\t\x12\x0e\n\x06strict\x18\x02 \x01(\x08\"u\n\x0eResponseFormat\x12\x0e\n\x04text\x18\x01 \x01(\x08H\x00\x12\x0e\n\x04json\x18\x02 \x01(\x08H\x00\x12\x39\n\x0bjson_schema\x18\x03 \x01(\x0b\x32\".amplifier.module.JsonSchemaFormatH\x00\x42\x08\n\x06\x66ormat\"\xf7\x01\n\x05Usage\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\x12\x1d\n\x10reasoning_tokens\x18\x04 \x01(\x05H\x00\x88\x01\x01\x12\x1e\n\x11\x63\x61\x63he_read_tokens\x18\x05 \x01(\x05H\x01\x88\x01\x01\x12\"\n\x15\x63\x61\x63he_creation_tokens\x18\x06 \x01(\x05H\x02\x88\x01\x01\x42\x13\n\x11_reasoning_tokensB\x14\n\x12_cache_read_tokensB\x18\n\x16_cache_creation_tokens\"@\n\x0b\x44\x65gradation\x12\x11\n\trequested\x18\x01 \x01(\t\x12\x0e\n\x06\x61\x63tual\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\"\x81\x03\n\x0b\x43hatRequest\x12+\n\x08messages\x18\x01 \x03(\x0b\x32\x19.amplifier.module.Message\x12.\n\x05tools\x18\x02 \x03(\x0b\x32\x1f.amplifier.module.ToolSpecProto\x12\x39\n\x0fresponse_format\x18\x03 \x01(\x0b\x32 .amplifier.module.ResponseFormat\x12\x13\n\x0btemperature\x18\x04 \x01(\x01\x12\r\n\x05top_p\x18\x05 \x01(\x01\x12\x19\n\x11max_output_tokens\x18\x06 \x01(\x05\x12\x17\n\x0f\x63onversation_id\x18\x07 \x01(\t\x12\x0e\n\x06stream\x18\x08 \x01(\x08\x12\x15\n\rmetadata_json\x18\t \x01(\t\x12\r\n\x05model\x18\n \x01(\t\x12\x13\n\x0btool_choice\x18\x0b \x01(\t\x12\x0c\n\x04stop\x18\x0c \x03(\t\x12\x18\n\x10reasoning_effort\x18\r \x01(\t\x12\x0f\n\x07timeout\x18\x0e \x01(\x01\"\x98\x02\n\x0c\x43hatResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x35\n\ntool_calls\x18\x02 \x03(\x0b\x32!.amplifier.module.ToolCallMessage\x12&\n\x05usage\x18\x03 \x01(\x0b\x32\x17.amplifier.module.Usage\x12\x32\n\x0b\x64\x65gradation\x18\x04 \x01(\x0b\x32\x1d.amplifier.module.Degradation\x12\x15\n\rfinish_reason\x18\x05 \x01(\t\x12\x15\n\rmetadata_json\x18\x06 \x01(\t\x12\x36\n\x0e\x63ontent_blocks\x18\x07 \x03(\x0b\x32\x1e.amplifier.module.ContentBlock\"F\n\nToolResult\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x13\n\x0boutput_json\x18\x02 \x01(\t\x12\x12\n\nerror_json\x18\x03 \x01(\t\"\xa7\x04\n\nHookResult\x12,\n\x06\x61\x63tion\x18\x01 \x01(\x0e\x32\x1c.amplifier.module.HookAction\x12\x11\n\tdata_json\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x19\n\x11\x63ontext_injection\x18\x04 \x01(\t\x12\x46\n\x16\x63ontext_injection_role\x18\x05 \x01(\x0e\x32&.amplifier.module.ContextInjectionRole\x12\x11\n\tephemeral\x18\x06 \x01(\x08\x12\x17\n\x0f\x61pproval_prompt\x18\x07 \x01(\t\x12\x18\n\x10\x61pproval_options\x18\x08 \x03(\t\x12\x1d\n\x10\x61pproval_timeout\x18\t \x01(\x01H\x00\x88\x01\x01\x12;\n\x10\x61pproval_default\x18\n \x01(\x0e\x32!.amplifier.module.ApprovalDefault\x12\x17\n\x0fsuppress_output\x18\x0b \x01(\x08\x12\x14\n\x0cuser_message\x18\x0c \x01(\t\x12>\n\x12user_message_level\x18\r \x01(\x0e\x32\".amplifier.module.UserMessageLevel\x12\x1b\n\x13user_message_source\x18\x0e \x01(\t\x12\"\n\x1a\x61ppend_to_last_tool_result\x18\x0f \x01(\x08\x42\x13\n\x11_approval_timeout\"\x8d\x01\n\tModelInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x16\n\x0e\x63ontext_window\x18\x03 \x01(\x05\x12\x19\n\x11max_output_tokens\x18\x04 \x01(\x05\x12\x14\n\x0c\x63\x61pabilities\x18\x05 \x03(\t\x12\x15\n\rdefaults_json\x18\x06 \x01(\t\"\xb0\x01\n\x0cProviderInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0c\x64isplay_name\x18\x02 \x01(\t\x12\x1b\n\x13\x63redential_env_vars\x18\x03 \x03(\t\x12\x14\n\x0c\x63\x61pabilities\x18\x04 \x03(\t\x12\x15\n\rdefaults_json\x18\x05 \x01(\t\x12\x34\n\rconfig_fields\x18\x06 \x03(\x0b\x32\x1d.amplifier.module.ConfigField\"\x80\x01\n\x0f\x41pprovalRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x0e\n\x06\x61\x63tion\x18\x02 \x01(\t\x12\x14\n\x0c\x64\x65tails_json\x18\x03 \x01(\t\x12\x12\n\nrisk_level\x18\x04 \x01(\t\x12\x14\n\x07timeout\x18\x05 \x01(\x01H\x00\x88\x01\x01\x42\n\n\x08_timeout\"F\n\x10\x41pprovalResponse\x12\x10\n\x08\x61pproved\x18\x01 \x01(\x08\x12\x0e\n\x06reason\x18\x02 \x01(\t\x12\x10\n\x08remember\x18\x03 \x01(\x08\"A\n\x12ListModelsResponse\x12+\n\x06models\x18\x01 \x03(\x0b\x32\x1b.amplifier.module.ModelInfo\"O\n\x16ParseToolCallsResponse\x12\x35\n\ntool_calls\x18\x01 \x03(\x0b\x32!.amplifier.module.ToolCallMessage\"@\n\x1aOrchestratorExecuteRequest\x12\x0e\n\x06prompt\x18\x01 \x01(\t\x12\x12\n\nsession_id\x18\x02 \x01(\t\">\n\x1bOrchestratorExecuteResponse\x12\x10\n\x08response\x18\x01 \x01(\t\x12\r\n\x05\x65rror\x18\x02 \x01(\t\"?\n\x11\x41\x64\x64MessageRequest\x12*\n\x07message\x18\x01 \x01(\x0b\x32\x19.amplifier.module.Message\"B\n\x13GetMessagesResponse\x12+\n\x08messages\x18\x01 \x03(\x0b\x32\x19.amplifier.module.Message\"J\n\x1bGetMessagesForRequestParams\x12\x14\n\x0ctoken_budget\x18\x01 \x01(\x05\x12\x15\n\rprovider_name\x18\x02 \x01(\t\"A\n\x12SetMessagesRequest\x12+\n\x08messages\x18\x01 \x03(\x0b\x32\x19.amplifier.module.Message\"5\n\x11HookHandleRequest\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\tdata_json\x18\x02 \x01(\t\".\n\x17GetSubscriptionsRequest\x12\x13\n\x0b\x63onfig_json\x18\x01 \x01(\t\"V\n\x18GetSubscriptionsResponse\x12:\n\rsubscriptions\x18\x01 \x03(\x0b\x32#.amplifier.module.EventSubscription\"B\n\x11\x45ventSubscription\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x10\n\x08priority\x18\x02 \x01(\x05\x12\x0c\n\x04name\x18\x03 \x01(\t\"d\n\x1b\x43ompleteWithProviderRequest\x12\x15\n\rprovider_name\x18\x01 \x01(\t\x12.\n\x07request\x18\x02 \x01(\x0b\x32\x1d.amplifier.module.ChatRequest\";\n\x12\x45xecuteToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x12\n\ninput_json\x18\x02 \x01(\t\"3\n\x0f\x45mitHookRequest\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\tdata_json\x18\x02 \x01(\t\"V\n\x19\x45mitHookAndCollectRequest\x12\r\n\x05\x65vent\x18\x01 \x01(\t\x12\x11\n\tdata_json\x18\x02 \x01(\t\x12\x17\n\x0ftimeout_seconds\x18\x03 \x01(\x01\"4\n\x1a\x45mitHookAndCollectResponse\x12\x16\n\x0eresponses_json\x18\x01 \x03(\t\"(\n\x12GetMessagesRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"Y\n\x17KernelAddMessageRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12*\n\x07message\x18\x02 \x01(\x0b\x32\x19.amplifier.module.Message\"a\n\x17GetMountedModuleRequest\x12\x13\n\x0bmodule_name\x18\x01 \x01(\t\x12\x31\n\x0bmodule_type\x18\x02 \x01(\x0e\x32\x1c.amplifier.module.ModuleType\"U\n\x18GetMountedModuleResponse\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12*\n\x04info\x18\x02 \x01(\x0b\x32\x1c.amplifier.module.ModuleInfo\"=\n\x19RegisterCapabilityRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\nvalue_json\x18\x02 \x01(\t\"$\n\x14GetCapabilityRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\":\n\x15GetCapabilityResponse\x12\r\n\x05\x66ound\x18\x01 \x01(\x08\x12\x12\n\nvalue_json\x18\x02 \x01(\t*\xbc\x01\n\nModuleType\x12\x1b\n\x17MODULE_TYPE_UNSPECIFIED\x10\x00\x12\x18\n\x14MODULE_TYPE_PROVIDER\x10\x01\x12\x14\n\x10MODULE_TYPE_TOOL\x10\x02\x12\x14\n\x10MODULE_TYPE_HOOK\x10\x03\x12\x16\n\x12MODULE_TYPE_MEMORY\x10\x04\x12\x19\n\x15MODULE_TYPE_GUARDRAIL\x10\x05\x12\x18\n\x14MODULE_TYPE_APPROVAL\x10\x06*\x82\x01\n\x0cHealthStatus\x12\x1d\n\x19HEALTH_STATUS_UNSPECIFIED\x10\x00\x12\x19\n\x15HEALTH_STATUS_SERVING\x10\x01\x12\x1d\n\x19HEALTH_STATUS_NOT_SERVING\x10\x02\x12\x19\n\x15HEALTH_STATUS_UNKNOWN\x10\x03*\xad\x01\n\x0f\x43onfigFieldType\x12!\n\x1d\x43ONFIG_FIELD_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x43ONFIG_FIELD_TYPE_STRING\x10\x01\x12\x1c\n\x18\x43ONFIG_FIELD_TYPE_NUMBER\x10\x02\x12\x1d\n\x19\x43ONFIG_FIELD_TYPE_BOOLEAN\x10\x03\x12\x1c\n\x18\x43ONFIG_FIELD_TYPE_SECRET\x10\x04*\xd8\x02\n\x11ProviderErrorType\x12#\n\x1fPROVIDER_ERROR_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18PROVIDER_ERROR_TYPE_AUTH\x10\x01\x12\"\n\x1ePROVIDER_ERROR_TYPE_RATE_LIMIT\x10\x02\x12&\n\"PROVIDER_ERROR_TYPE_CONTEXT_LENGTH\x10\x03\x12\'\n#PROVIDER_ERROR_TYPE_INVALID_REQUEST\x10\x04\x12&\n\"PROVIDER_ERROR_TYPE_CONTENT_FILTER\x10\x05\x12#\n\x1fPROVIDER_ERROR_TYPE_UNAVAILABLE\x10\x06\x12\x1f\n\x1bPROVIDER_ERROR_TYPE_TIMEOUT\x10\x07\x12\x1d\n\x19PROVIDER_ERROR_TYPE_OTHER\x10\x08*\x8c\x01\n\rToolErrorType\x12\x1f\n\x1bTOOL_ERROR_TYPE_UNSPECIFIED\x10\x00\x12\x1d\n\x19TOOL_ERROR_TYPE_EXECUTION\x10\x01\x12\x1e\n\x1aTOOL_ERROR_TYPE_VALIDATION\x10\x02\x12\x1b\n\x17TOOL_ERROR_TYPE_TIMEOUT\x10\x03*\x8c\x01\n\rHookErrorType\x12\x1f\n\x1bHOOK_ERROR_TYPE_UNSPECIFIED\x10\x00\x12\x1d\n\x19HOOK_ERROR_TYPE_EXECUTION\x10\x01\x12\x1e\n\x1aHOOK_ERROR_TYPE_VALIDATION\x10\x02\x12\x1b\n\x17HOOK_ERROR_TYPE_TIMEOUT\x10\x03*\x86\x01\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04\x12\x11\n\rROLE_FUNCTION\x10\x05\x12\x12\n\x0eROLE_DEVELOPER\x10\x06*o\n\nVisibility\x12\x1a\n\x16VISIBILITY_UNSPECIFIED\x10\x00\x12\x12\n\x0eVISIBILITY_ALL\x10\x01\x12\x17\n\x13VISIBILITY_LLM_ONLY\x10\x02\x12\x18\n\x14VISIBILITY_USER_ONLY\x10\x03*\xab\x01\n\nHookAction\x12\x1b\n\x17HOOK_ACTION_UNSPECIFIED\x10\x00\x12\x18\n\x14HOOK_ACTION_CONTINUE\x10\x01\x12\x16\n\x12HOOK_ACTION_MODIFY\x10\x02\x12\x14\n\x10HOOK_ACTION_DENY\x10\x03\x12\x1e\n\x1aHOOK_ACTION_INJECT_CONTEXT\x10\x04\x12\x18\n\x14HOOK_ACTION_ASK_USER\x10\x05*\xa8\x01\n\x14\x43ontextInjectionRole\x12&\n\"CONTEXT_INJECTION_ROLE_UNSPECIFIED\x10\x00\x12!\n\x1d\x43ONTEXT_INJECTION_ROLE_SYSTEM\x10\x01\x12\x1f\n\x1b\x43ONTEXT_INJECTION_ROLE_USER\x10\x02\x12$\n CONTEXT_INJECTION_ROLE_ASSISTANT\x10\x03*l\n\x0f\x41pprovalDefault\x12 \n\x1c\x41PPROVAL_DEFAULT_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x41PPROVAL_DEFAULT_APPROVE\x10\x01\x12\x19\n\x15\x41PPROVAL_DEFAULT_DENY\x10\x02*\x91\x01\n\x10UserMessageLevel\x12\"\n\x1eUSER_MESSAGE_LEVEL_UNSPECIFIED\x10\x00\x12\x1b\n\x17USER_MESSAGE_LEVEL_INFO\x10\x01\x12\x1e\n\x1aUSER_MESSAGE_LEVEL_WARNING\x10\x02\x12\x1c\n\x18USER_MESSAGE_LEVEL_ERROR\x10\x03\x32\xa5\x01\n\x0bToolService\x12>\n\x07GetSpec\x12\x17.amplifier.module.Empty\x1a\x1a.amplifier.module.ToolSpec\x12V\n\x07\x45xecute\x12$.amplifier.module.ToolExecuteRequest\x1a%.amplifier.module.ToolExecuteResponse2\x9f\x03\n\x0fProviderService\x12\x42\n\x07GetInfo\x12\x17.amplifier.module.Empty\x1a\x1e.amplifier.module.ProviderInfo\x12K\n\nListModels\x12\x17.amplifier.module.Empty\x1a$.amplifier.module.ListModelsResponse\x12I\n\x08\x43omplete\x12\x1d.amplifier.module.ChatRequest\x1a\x1e.amplifier.module.ChatResponse\x12T\n\x11\x43ompleteStreaming\x12\x1d.amplifier.module.ChatRequest\x1a\x1e.amplifier.module.ChatResponse0\x01\x12Z\n\x0eParseToolCalls\x12\x1e.amplifier.module.ChatResponse\x1a(.amplifier.module.ParseToolCallsResponse2}\n\x13OrchestratorService\x12\x66\n\x07\x45xecute\x12,.amplifier.module.OrchestratorExecuteRequest\x1a-.amplifier.module.OrchestratorExecuteResponse2\xa3\x03\n\x0e\x43ontextService\x12J\n\nAddMessage\x12#.amplifier.module.AddMessageRequest\x1a\x17.amplifier.module.Empty\x12M\n\x0bGetMessages\x12\x17.amplifier.module.Empty\x1a%.amplifier.module.GetMessagesResponse\x12m\n\x15GetMessagesForRequest\x12-.amplifier.module.GetMessagesForRequestParams\x1a%.amplifier.module.GetMessagesResponse\x12L\n\x0bSetMessages\x12$.amplifier.module.SetMessagesRequest\x1a\x17.amplifier.module.Empty\x12\x39\n\x05\x43lear\x12\x17.amplifier.module.Empty\x1a\x17.amplifier.module.Empty2\xc5\x01\n\x0bHookService\x12K\n\x06Handle\x12#.amplifier.module.HookHandleRequest\x1a\x1c.amplifier.module.HookResult\x12i\n\x10GetSubscriptions\x12).amplifier.module.GetSubscriptionsRequest\x1a*.amplifier.module.GetSubscriptionsResponse2k\n\x0f\x41pprovalService\x12X\n\x0fRequestApproval\x12!.amplifier.module.ApprovalRequest\x1a\".amplifier.module.ApprovalResponse2\xd0\x07\n\rKernelService\x12\x65\n\x14\x43ompleteWithProvider\x12-.amplifier.module.CompleteWithProviderRequest\x1a\x1e.amplifier.module.ChatResponse\x12p\n\x1d\x43ompleteWithProviderStreaming\x12-.amplifier.module.CompleteWithProviderRequest\x1a\x1e.amplifier.module.ChatResponse0\x01\x12Q\n\x0b\x45xecuteTool\x12$.amplifier.module.ExecuteToolRequest\x1a\x1c.amplifier.module.ToolResult\x12K\n\x08\x45mitHook\x12!.amplifier.module.EmitHookRequest\x1a\x1c.amplifier.module.HookResult\x12o\n\x12\x45mitHookAndCollect\x12+.amplifier.module.EmitHookAndCollectRequest\x1a,.amplifier.module.EmitHookAndCollectResponse\x12Z\n\x0bGetMessages\x12$.amplifier.module.GetMessagesRequest\x1a%.amplifier.module.GetMessagesResponse\x12P\n\nAddMessage\x12).amplifier.module.KernelAddMessageRequest\x1a\x17.amplifier.module.Empty\x12i\n\x10GetMountedModule\x12).amplifier.module.GetMountedModuleRequest\x1a*.amplifier.module.GetMountedModuleResponse\x12Z\n\x12RegisterCapability\x12+.amplifier.module.RegisterCapabilityRequest\x1a\x17.amplifier.module.Empty\x12`\n\rGetCapability\x12&.amplifier.module.GetCapabilityRequest\x1a\'.amplifier.module.GetCapabilityResponse2\xaf\x02\n\x0fModuleLifecycle\x12H\n\x05Mount\x12\x1e.amplifier.module.MountRequest\x1a\x1f.amplifier.module.MountResponse\x12;\n\x07\x43leanup\x12\x17.amplifier.module.Empty\x1a\x17.amplifier.module.Empty\x12M\n\x0bHealthCheck\x12\x17.amplifier.module.Empty\x1a%.amplifier.module.HealthCheckResponse\x12\x46\n\rGetModuleInfo\x12\x17.amplifier.module.Empty\x1a\x1c.amplifier.module.ModuleInfob\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -35,30 +35,30 @@ _globals['_MOUNTREQUEST_CONFIGENTRY']._serialized_options = b'8\001' _globals['_CONFIGFIELD_SHOWWHENENTRY']._loaded_options = None _globals['_CONFIGFIELD_SHOWWHENENTRY']._serialized_options = b'8\001' - _globals['_MODULETYPE']._serialized_start=7149 - _globals['_MODULETYPE']._serialized_end=7337 - _globals['_HEALTHSTATUS']._serialized_start=7340 - _globals['_HEALTHSTATUS']._serialized_end=7470 - _globals['_CONFIGFIELDTYPE']._serialized_start=7473 - _globals['_CONFIGFIELDTYPE']._serialized_end=7646 - _globals['_PROVIDERERRORTYPE']._serialized_start=7649 - _globals['_PROVIDERERRORTYPE']._serialized_end=7993 - _globals['_TOOLERRORTYPE']._serialized_start=7996 - _globals['_TOOLERRORTYPE']._serialized_end=8136 - _globals['_HOOKERRORTYPE']._serialized_start=8139 - _globals['_HOOKERRORTYPE']._serialized_end=8279 - _globals['_ROLE']._serialized_start=8282 - _globals['_ROLE']._serialized_end=8416 - _globals['_VISIBILITY']._serialized_start=8418 - _globals['_VISIBILITY']._serialized_end=8529 - _globals['_HOOKACTION']._serialized_start=8532 - _globals['_HOOKACTION']._serialized_end=8703 - _globals['_CONTEXTINJECTIONROLE']._serialized_start=8706 - _globals['_CONTEXTINJECTIONROLE']._serialized_end=8874 - _globals['_APPROVALDEFAULT']._serialized_start=8876 - _globals['_APPROVALDEFAULT']._serialized_end=8984 - _globals['_USERMESSAGELEVEL']._serialized_start=8987 - _globals['_USERMESSAGELEVEL']._serialized_end=9132 + _globals['_MODULETYPE']._serialized_start=7113 + _globals['_MODULETYPE']._serialized_end=7301 + _globals['_HEALTHSTATUS']._serialized_start=7304 + _globals['_HEALTHSTATUS']._serialized_end=7434 + _globals['_CONFIGFIELDTYPE']._serialized_start=7437 + _globals['_CONFIGFIELDTYPE']._serialized_end=7610 + _globals['_PROVIDERERRORTYPE']._serialized_start=7613 + _globals['_PROVIDERERRORTYPE']._serialized_end=7957 + _globals['_TOOLERRORTYPE']._serialized_start=7960 + _globals['_TOOLERRORTYPE']._serialized_end=8100 + _globals['_HOOKERRORTYPE']._serialized_start=8103 + _globals['_HOOKERRORTYPE']._serialized_end=8243 + _globals['_ROLE']._serialized_start=8246 + _globals['_ROLE']._serialized_end=8380 + _globals['_VISIBILITY']._serialized_start=8382 + _globals['_VISIBILITY']._serialized_end=8493 + _globals['_HOOKACTION']._serialized_start=8496 + _globals['_HOOKACTION']._serialized_end=8667 + _globals['_CONTEXTINJECTIONROLE']._serialized_start=8670 + _globals['_CONTEXTINJECTIONROLE']._serialized_end=8838 + _globals['_APPROVALDEFAULT']._serialized_start=8840 + _globals['_APPROVALDEFAULT']._serialized_end=8948 + _globals['_USERMESSAGELEVEL']._serialized_start=8951 + _globals['_USERMESSAGELEVEL']._serialized_end=9096 _globals['_EMPTY']._serialized_start=44 _globals['_EMPTY']._serialized_end=51 _globals['_TOOLSPEC']._serialized_start=53 @@ -118,87 +118,87 @@ _globals['_RESPONSEFORMAT']._serialized_start=3203 _globals['_RESPONSEFORMAT']._serialized_end=3320 _globals['_USAGE']._serialized_start=3323 - _globals['_USAGE']._serialized_end=3606 - _globals['_DEGRADATION']._serialized_start=3608 - _globals['_DEGRADATION']._serialized_end=3672 - _globals['_CHATREQUEST']._serialized_start=3675 - _globals['_CHATREQUEST']._serialized_end=4060 - _globals['_CHATRESPONSE']._serialized_start=4063 - _globals['_CHATRESPONSE']._serialized_end=4343 - _globals['_TOOLRESULT']._serialized_start=4345 - _globals['_TOOLRESULT']._serialized_end=4415 - _globals['_HOOKRESULT']._serialized_start=4418 - _globals['_HOOKRESULT']._serialized_end=4969 - _globals['_MODELINFO']._serialized_start=4972 - _globals['_MODELINFO']._serialized_end=5113 - _globals['_PROVIDERINFO']._serialized_start=5116 - _globals['_PROVIDERINFO']._serialized_end=5292 - _globals['_APPROVALREQUEST']._serialized_start=5295 - _globals['_APPROVALREQUEST']._serialized_end=5423 - _globals['_APPROVALRESPONSE']._serialized_start=5425 - _globals['_APPROVALRESPONSE']._serialized_end=5495 - _globals['_LISTMODELSRESPONSE']._serialized_start=5497 - _globals['_LISTMODELSRESPONSE']._serialized_end=5562 - _globals['_PARSETOOLCALLSRESPONSE']._serialized_start=5564 - _globals['_PARSETOOLCALLSRESPONSE']._serialized_end=5643 - _globals['_ORCHESTRATOREXECUTEREQUEST']._serialized_start=5645 - _globals['_ORCHESTRATOREXECUTEREQUEST']._serialized_end=5709 - _globals['_ORCHESTRATOREXECUTERESPONSE']._serialized_start=5711 - _globals['_ORCHESTRATOREXECUTERESPONSE']._serialized_end=5773 - _globals['_ADDMESSAGEREQUEST']._serialized_start=5775 - _globals['_ADDMESSAGEREQUEST']._serialized_end=5838 - _globals['_GETMESSAGESRESPONSE']._serialized_start=5840 - _globals['_GETMESSAGESRESPONSE']._serialized_end=5906 - _globals['_GETMESSAGESFORREQUESTPARAMS']._serialized_start=5908 - _globals['_GETMESSAGESFORREQUESTPARAMS']._serialized_end=5982 - _globals['_SETMESSAGESREQUEST']._serialized_start=5984 - _globals['_SETMESSAGESREQUEST']._serialized_end=6049 - _globals['_HOOKHANDLEREQUEST']._serialized_start=6051 - _globals['_HOOKHANDLEREQUEST']._serialized_end=6104 - _globals['_GETSUBSCRIPTIONSREQUEST']._serialized_start=6106 - _globals['_GETSUBSCRIPTIONSREQUEST']._serialized_end=6152 - _globals['_GETSUBSCRIPTIONSRESPONSE']._serialized_start=6154 - _globals['_GETSUBSCRIPTIONSRESPONSE']._serialized_end=6240 - _globals['_EVENTSUBSCRIPTION']._serialized_start=6242 - _globals['_EVENTSUBSCRIPTION']._serialized_end=6308 - _globals['_COMPLETEWITHPROVIDERREQUEST']._serialized_start=6310 - _globals['_COMPLETEWITHPROVIDERREQUEST']._serialized_end=6410 - _globals['_EXECUTETOOLREQUEST']._serialized_start=6412 - _globals['_EXECUTETOOLREQUEST']._serialized_end=6471 - _globals['_EMITHOOKREQUEST']._serialized_start=6473 - _globals['_EMITHOOKREQUEST']._serialized_end=6524 - _globals['_EMITHOOKANDCOLLECTREQUEST']._serialized_start=6526 - _globals['_EMITHOOKANDCOLLECTREQUEST']._serialized_end=6612 - _globals['_EMITHOOKANDCOLLECTRESPONSE']._serialized_start=6614 - _globals['_EMITHOOKANDCOLLECTRESPONSE']._serialized_end=6666 - _globals['_GETMESSAGESREQUEST']._serialized_start=6668 - _globals['_GETMESSAGESREQUEST']._serialized_end=6708 - _globals['_KERNELADDMESSAGEREQUEST']._serialized_start=6710 - _globals['_KERNELADDMESSAGEREQUEST']._serialized_end=6799 - _globals['_GETMOUNTEDMODULEREQUEST']._serialized_start=6801 - _globals['_GETMOUNTEDMODULEREQUEST']._serialized_end=6898 - _globals['_GETMOUNTEDMODULERESPONSE']._serialized_start=6900 - _globals['_GETMOUNTEDMODULERESPONSE']._serialized_end=6985 - _globals['_REGISTERCAPABILITYREQUEST']._serialized_start=6987 - _globals['_REGISTERCAPABILITYREQUEST']._serialized_end=7048 - _globals['_GETCAPABILITYREQUEST']._serialized_start=7050 - _globals['_GETCAPABILITYREQUEST']._serialized_end=7086 - _globals['_GETCAPABILITYRESPONSE']._serialized_start=7088 - _globals['_GETCAPABILITYRESPONSE']._serialized_end=7146 - _globals['_TOOLSERVICE']._serialized_start=9135 - _globals['_TOOLSERVICE']._serialized_end=9300 - _globals['_PROVIDERSERVICE']._serialized_start=9303 - _globals['_PROVIDERSERVICE']._serialized_end=9718 - _globals['_ORCHESTRATORSERVICE']._serialized_start=9720 - _globals['_ORCHESTRATORSERVICE']._serialized_end=9845 - _globals['_CONTEXTSERVICE']._serialized_start=9848 - _globals['_CONTEXTSERVICE']._serialized_end=10267 - _globals['_HOOKSERVICE']._serialized_start=10270 - _globals['_HOOKSERVICE']._serialized_end=10467 - _globals['_APPROVALSERVICE']._serialized_start=10469 - _globals['_APPROVALSERVICE']._serialized_end=10576 - _globals['_KERNELSERVICE']._serialized_start=10579 - _globals['_KERNELSERVICE']._serialized_end=11555 - _globals['_MODULELIFECYCLE']._serialized_start=11558 - _globals['_MODULELIFECYCLE']._serialized_end=11861 + _globals['_USAGE']._serialized_end=3570 + _globals['_DEGRADATION']._serialized_start=3572 + _globals['_DEGRADATION']._serialized_end=3636 + _globals['_CHATREQUEST']._serialized_start=3639 + _globals['_CHATREQUEST']._serialized_end=4024 + _globals['_CHATRESPONSE']._serialized_start=4027 + _globals['_CHATRESPONSE']._serialized_end=4307 + _globals['_TOOLRESULT']._serialized_start=4309 + _globals['_TOOLRESULT']._serialized_end=4379 + _globals['_HOOKRESULT']._serialized_start=4382 + _globals['_HOOKRESULT']._serialized_end=4933 + _globals['_MODELINFO']._serialized_start=4936 + _globals['_MODELINFO']._serialized_end=5077 + _globals['_PROVIDERINFO']._serialized_start=5080 + _globals['_PROVIDERINFO']._serialized_end=5256 + _globals['_APPROVALREQUEST']._serialized_start=5259 + _globals['_APPROVALREQUEST']._serialized_end=5387 + _globals['_APPROVALRESPONSE']._serialized_start=5389 + _globals['_APPROVALRESPONSE']._serialized_end=5459 + _globals['_LISTMODELSRESPONSE']._serialized_start=5461 + _globals['_LISTMODELSRESPONSE']._serialized_end=5526 + _globals['_PARSETOOLCALLSRESPONSE']._serialized_start=5528 + _globals['_PARSETOOLCALLSRESPONSE']._serialized_end=5607 + _globals['_ORCHESTRATOREXECUTEREQUEST']._serialized_start=5609 + _globals['_ORCHESTRATOREXECUTEREQUEST']._serialized_end=5673 + _globals['_ORCHESTRATOREXECUTERESPONSE']._serialized_start=5675 + _globals['_ORCHESTRATOREXECUTERESPONSE']._serialized_end=5737 + _globals['_ADDMESSAGEREQUEST']._serialized_start=5739 + _globals['_ADDMESSAGEREQUEST']._serialized_end=5802 + _globals['_GETMESSAGESRESPONSE']._serialized_start=5804 + _globals['_GETMESSAGESRESPONSE']._serialized_end=5870 + _globals['_GETMESSAGESFORREQUESTPARAMS']._serialized_start=5872 + _globals['_GETMESSAGESFORREQUESTPARAMS']._serialized_end=5946 + _globals['_SETMESSAGESREQUEST']._serialized_start=5948 + _globals['_SETMESSAGESREQUEST']._serialized_end=6013 + _globals['_HOOKHANDLEREQUEST']._serialized_start=6015 + _globals['_HOOKHANDLEREQUEST']._serialized_end=6068 + _globals['_GETSUBSCRIPTIONSREQUEST']._serialized_start=6070 + _globals['_GETSUBSCRIPTIONSREQUEST']._serialized_end=6116 + _globals['_GETSUBSCRIPTIONSRESPONSE']._serialized_start=6118 + _globals['_GETSUBSCRIPTIONSRESPONSE']._serialized_end=6204 + _globals['_EVENTSUBSCRIPTION']._serialized_start=6206 + _globals['_EVENTSUBSCRIPTION']._serialized_end=6272 + _globals['_COMPLETEWITHPROVIDERREQUEST']._serialized_start=6274 + _globals['_COMPLETEWITHPROVIDERREQUEST']._serialized_end=6374 + _globals['_EXECUTETOOLREQUEST']._serialized_start=6376 + _globals['_EXECUTETOOLREQUEST']._serialized_end=6435 + _globals['_EMITHOOKREQUEST']._serialized_start=6437 + _globals['_EMITHOOKREQUEST']._serialized_end=6488 + _globals['_EMITHOOKANDCOLLECTREQUEST']._serialized_start=6490 + _globals['_EMITHOOKANDCOLLECTREQUEST']._serialized_end=6576 + _globals['_EMITHOOKANDCOLLECTRESPONSE']._serialized_start=6578 + _globals['_EMITHOOKANDCOLLECTRESPONSE']._serialized_end=6630 + _globals['_GETMESSAGESREQUEST']._serialized_start=6632 + _globals['_GETMESSAGESREQUEST']._serialized_end=6672 + _globals['_KERNELADDMESSAGEREQUEST']._serialized_start=6674 + _globals['_KERNELADDMESSAGEREQUEST']._serialized_end=6763 + _globals['_GETMOUNTEDMODULEREQUEST']._serialized_start=6765 + _globals['_GETMOUNTEDMODULEREQUEST']._serialized_end=6862 + _globals['_GETMOUNTEDMODULERESPONSE']._serialized_start=6864 + _globals['_GETMOUNTEDMODULERESPONSE']._serialized_end=6949 + _globals['_REGISTERCAPABILITYREQUEST']._serialized_start=6951 + _globals['_REGISTERCAPABILITYREQUEST']._serialized_end=7012 + _globals['_GETCAPABILITYREQUEST']._serialized_start=7014 + _globals['_GETCAPABILITYREQUEST']._serialized_end=7050 + _globals['_GETCAPABILITYRESPONSE']._serialized_start=7052 + _globals['_GETCAPABILITYRESPONSE']._serialized_end=7110 + _globals['_TOOLSERVICE']._serialized_start=9099 + _globals['_TOOLSERVICE']._serialized_end=9264 + _globals['_PROVIDERSERVICE']._serialized_start=9267 + _globals['_PROVIDERSERVICE']._serialized_end=9682 + _globals['_ORCHESTRATORSERVICE']._serialized_start=9684 + _globals['_ORCHESTRATORSERVICE']._serialized_end=9809 + _globals['_CONTEXTSERVICE']._serialized_start=9812 + _globals['_CONTEXTSERVICE']._serialized_end=10231 + _globals['_HOOKSERVICE']._serialized_start=10234 + _globals['_HOOKSERVICE']._serialized_end=10431 + _globals['_APPROVALSERVICE']._serialized_start=10433 + _globals['_APPROVALSERVICE']._serialized_end=10540 + _globals['_KERNELSERVICE']._serialized_start=10543 + _globals['_KERNELSERVICE']._serialized_end=11519 + _globals['_MODULELIFECYCLE']._serialized_start=11522 + _globals['_MODULELIFECYCLE']._serialized_end=11825 # @@protoc_insertion_point(module_scope) diff --git a/proto/test_task03_module_specific.py b/proto/test_task03_module_specific.py deleted file mode 100644 index 3c0fc2e3..00000000 --- a/proto/test_task03_module_specific.py +++ /dev/null @@ -1,260 +0,0 @@ -"""TDD test for Task 03: Module-specific messages in amplifier_module.proto. - -Tests proto compilation and verifies all required types are present. -""" -import subprocess -import re -import sys -import os -import tempfile - -PROTO_PATH = os.path.join(os.path.dirname(__file__), "amplifier_module.proto") - - -def read_proto(): - with open(PROTO_PATH, "r") as f: - return f.read() - - -def field_present(body, field_spec): - """Check if a field like 'bool success' is present, tolerating extra whitespace.""" - # Split field_spec into parts and join with \s+ for flexible matching - parts = field_spec.split() - pattern = r'\s+'.join(re.escape(p) for p in parts) - return bool(re.search(pattern, body)) - - -def test_proto_compiles(): - """Proto must compile with exit code 0.""" - with tempfile.TemporaryDirectory() as tmpdir: - result = subprocess.run( - ["protoc", f"--proto_path={os.path.dirname(PROTO_PATH)}", - f"--python_out={tmpdir}", PROTO_PATH], - capture_output=True, text=True - ) - assert result.returncode == 0, f"protoc failed:\n{result.stderr}" - - -# --------------------------------------------------------------------------- -# Enums -# --------------------------------------------------------------------------- - -def test_hook_action_enum(): - """HookAction enum with 6 values: UNSPECIFIED through ASK_USER.""" - content = read_proto() - assert "enum HookAction" in content, "Missing enum HookAction" - # Extract enum body - m = re.search(r'enum HookAction\s*\{([^}]+)\}', content) - assert m, "Cannot parse HookAction enum body" - body = m.group(1) - expected = [ - "HOOK_ACTION_UNSPECIFIED", - "HOOK_ACTION_CONTINUE", - "HOOK_ACTION_MODIFY", - "HOOK_ACTION_SKIP", - "HOOK_ACTION_BLOCK", - "HOOK_ACTION_ASK_USER", - ] - for val in expected: - assert val in body, f"HookAction missing value: {val}" - - -def test_context_injection_role_enum(): - """ContextInjectionRole enum with 4 values.""" - content = read_proto() - assert "enum ContextInjectionRole" in content, "Missing enum ContextInjectionRole" - m = re.search(r'enum ContextInjectionRole\s*\{([^}]+)\}', content) - assert m, "Cannot parse ContextInjectionRole enum body" - body = m.group(1) - expected = [ - "CONTEXT_INJECTION_ROLE_UNSPECIFIED", - "CONTEXT_INJECTION_ROLE_SYSTEM", - "CONTEXT_INJECTION_ROLE_USER", - "CONTEXT_INJECTION_ROLE_ASSISTANT", - ] - for val in expected: - assert val in body, f"ContextInjectionRole missing value: {val}" - - -def test_approval_default_enum(): - """ApprovalDefault enum with 3 values.""" - content = read_proto() - assert "enum ApprovalDefault" in content, "Missing enum ApprovalDefault" - m = re.search(r'enum ApprovalDefault\s*\{([^}]+)\}', content) - assert m, "Cannot parse ApprovalDefault enum body" - body = m.group(1) - expected = [ - "APPROVAL_DEFAULT_UNSPECIFIED", - "APPROVAL_DEFAULT_APPROVE", - "APPROVAL_DEFAULT_DENY", - ] - for val in expected: - assert val in body, f"ApprovalDefault missing value: {val}" - - -def test_user_message_level_enum(): - """UserMessageLevel enum with 4 values.""" - content = read_proto() - assert "enum UserMessageLevel" in content, "Missing enum UserMessageLevel" - m = re.search(r'enum UserMessageLevel\s*\{([^}]+)\}', content) - assert m, "Cannot parse UserMessageLevel enum body" - body = m.group(1) - expected = [ - "USER_MESSAGE_LEVEL_UNSPECIFIED", - "USER_MESSAGE_LEVEL_INFO", - "USER_MESSAGE_LEVEL_WARNING", - "USER_MESSAGE_LEVEL_ERROR", - ] - for val in expected: - assert val in body, f"UserMessageLevel missing value: {val}" - - -# --------------------------------------------------------------------------- -# Messages -# --------------------------------------------------------------------------- - -def test_tool_result_message(): - """ToolResult message with 3 fields: success, output_json, error_json.""" - content = read_proto() - assert "message ToolResult" in content, "Missing message ToolResult" - m = re.search(r'message ToolResult\s*\{([^}]+)\}', content) - assert m, "Cannot parse ToolResult body" - body = m.group(1) - assert field_present(body, "bool success"), "ToolResult missing field: success" - assert field_present(body, "string output_json"), "ToolResult missing field: output_json" - assert field_present(body, "string error_json"), "ToolResult missing field: error_json" - - -def test_hook_result_message_15_fields(): - """HookResult must have all 15 fields.""" - content = read_proto() - assert "message HookResult" in content, "Missing message HookResult" - m = re.search(r'message HookResult\s*\{([^}]+)\}', content) - assert m, "Cannot parse HookResult body" - body = m.group(1) - expected_fields = [ - "HookAction action", - "string data_json", - "string reason", - "string context_injection", - "ContextInjectionRole context_injection_role", - "bool ephemeral", - "string approval_prompt", - "repeated string approval_options", - "double approval_timeout", - "ApprovalDefault approval_default", - "bool suppress_output", - "string user_message", - "UserMessageLevel user_message_level", - "string user_message_source", - "bool append_to_last_tool_result", - ] - for field in expected_fields: - assert field_present(body, field), f"HookResult missing field: {field}" - # Verify approval_timeout default is 300.0 - # proto3 doesn't support default values natively; check for a comment - assert "300" in body, "HookResult: approval_timeout should reference default 300" - - -def test_model_info_message(): - """ModelInfo message with 6 fields.""" - content = read_proto() - assert "message ModelInfo" in content, "Missing message ModelInfo" - m = re.search(r'message ModelInfo\s*\{([^}]+)\}', content) - assert m, "Cannot parse ModelInfo body" - body = m.group(1) - expected_fields = [ - "string id", - "string display_name", - "int32 context_window", - "int32 max_output_tokens", - "repeated string capabilities", - "string defaults_json", - ] - for field in expected_fields: - assert field_present(body, field), f"ModelInfo missing field: {field}" - - -def test_provider_info_message(): - """ProviderInfo message with 6 fields including config_fields.""" - content = read_proto() - assert "message ProviderInfo" in content, "Missing message ProviderInfo" - m = re.search(r'message ProviderInfo\s*\{([^}]+)\}', content) - assert m, "Cannot parse ProviderInfo body" - body = m.group(1) - assert "config_fields" in body, "ProviderInfo missing field: config_fields" - # Count fields (lines with field numbers) - field_numbers = re.findall(r'=\s*\d+', body) - assert len(field_numbers) >= 6, f"ProviderInfo should have >= 6 fields, found {len(field_numbers)}" - - -def test_approval_request_message(): - """ApprovalRequest with 5 fields: tool_name, action, details_json, risk_level, timeout.""" - content = read_proto() - assert "message ApprovalRequest" in content, "Missing message ApprovalRequest" - m = re.search(r'message ApprovalRequest\s*\{([^}]+)\}', content) - assert m, "Cannot parse ApprovalRequest body" - body = m.group(1) - expected_fields = [ - "string tool_name", - "string action", - "string details_json", - "string risk_level", - "double timeout", - ] - for field in expected_fields: - assert field_present(body, field), f"ApprovalRequest missing field: {field}" - - -def test_approval_response_message(): - """ApprovalResponse with 3 fields: approved, reason, remember.""" - content = read_proto() - assert "message ApprovalResponse" in content, "Missing message ApprovalResponse" - m = re.search(r'message ApprovalResponse\s*\{([^}]+)\}', content) - assert m, "Cannot parse ApprovalResponse body" - body = m.group(1) - expected_fields = [ - "bool approved", - "string reason", - "bool remember", - ] - for field in expected_fields: - assert field_present(body, field), f"ApprovalResponse missing field: {field}" - - - - -def test_usage_message_has_cost_usd(): - """Usage message must have cost_usd as optional string field 7. - - String type matches Decimal JSON serialization on the Python/SessionStatus side. - None means unknown cost (not zero). - """ - content = read_proto() - assert "message Usage" in content, "Missing message Usage" - m = re.search(r'message Usage\s*\{([^}]+)\}', content) - assert m, "Cannot parse Usage body" - body = m.group(1) - assert "cost_usd" in body, ( - "Usage message missing field cost_usd. " - "Add: optional string cost_usd = 7; // Decimal as string; None = unknown cost" - ) - assert field_present(body, "string cost_usd"), ( - f"cost_usd should be type 'string' (Decimal serializes as string), got: {body}" - ) - -if __name__ == "__main__": - # Run all test functions - failed = [] - passed = [] - for name, obj in sorted(globals().items()): - if name.startswith("test_") and callable(obj): - try: - obj() - passed.append(name) - print(f" PASS: {name}") - except AssertionError as e: - failed.append((name, str(e))) - print(f" FAIL: {name} -> {e}") - print(f"\n{len(passed)} passed, {len(failed)} failed") - sys.exit(1 if failed else 0) diff --git a/pyproject.toml b/pyproject.toml index 550e2e22..4c3df7ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "amplifier-core" -version = "1.4.0" +version = "1.5.0" description = "Rust kernel with Python bindings for the Amplifier modular AI agent framework" license = "MIT" readme = "README.md" diff --git a/python/amplifier_core/__init__.py b/python/amplifier_core/__init__.py index 700e4d37..42a6e582 100644 --- a/python/amplifier_core/__init__.py +++ b/python/amplifier_core/__init__.py @@ -6,7 +6,7 @@ AmplifierSession`) still give the pure-Python implementations. """ -__version__ = "1.4.0" +__version__ = "1.5.0" # --- Rust-backed primary types (THE SWITCHOVER) --- # These four were previously imported from their Python submodules. diff --git a/python/amplifier_core/message_models.py b/python/amplifier_core/message_models.py index dd86c3fc..d7e069a0 100644 --- a/python/amplifier_core/message_models.py +++ b/python/amplifier_core/message_models.py @@ -245,7 +245,14 @@ class Usage(BaseModel): reasoning_tokens: int | None = None cache_read_tokens: int | None = None cache_write_tokens: int | None = None - cost_usd: Decimal | None = None + cost_usd: Decimal | None = Field( + default=None, + description=( + "Message cost in USD. " + "None = rate data unavailable (not zero). " + "Populated by provider." + ), + ) @field_validator("cost_usd", mode="before") @classmethod diff --git a/python/amplifier_core/models.py b/python/amplifier_core/models.py index e8540386..bb7faa07 100644 --- a/python/amplifier_core/models.py +++ b/python/amplifier_core/models.py @@ -428,12 +428,6 @@ class SessionStatus(BaseModel): "Populated by provider session contributors." ), ) - estimated_cost: float | None = Field( - default=None, - deprecated=True, - description="Deprecated: use cost_usd (Decimal). Will be removed in a future release.", - ) - @field_validator("cost_usd", mode="before") @classmethod def reject_float_cost_usd(cls, v): diff --git a/uv.lock b/uv.lock index 34fc6719..ba87867c 100644 --- a/uv.lock +++ b/uv.lock @@ -4,7 +4,7 @@ requires-python = ">=3.11" [[package]] name = "amplifier-core" -version = "1.4.1" +version = "1.5.0" source = { editable = "." } dependencies = [ { name = "click" }, From 6da0de4d186ebb46207c530b47cf6f0f6853897e Mon Sep 17 00:00:00 2001 From: Ken Chau Date: Mon, 4 May 2026 21:16:14 -0700 Subject: [PATCH 09/11] =?UTF-8?q?docs:=20document=20String=20type=20choice?= =?UTF-8?q?=20for=20cost=5Fusd=20=E2=80=94=20no=20rust=5Fdecimal=20depende?= =?UTF-8?q?ncy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kernel stores cost_usd as Option rather than rust_decimal::Decimal deliberately: - kernel does no arithmetic on cost (transport-only field) - type enforcement (Decimal, float rejection) belongs in Python - avoids rust_decimal dependency in the kernel If cost arithmetic ever moves into the kernel, the type must change. --- crates/amplifier-core/src/models.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/amplifier-core/src/models.rs b/crates/amplifier-core/src/models.rs index 5b5c6429..b790c679 100644 --- a/crates/amplifier-core/src/models.rs +++ b/crates/amplifier-core/src/models.rs @@ -451,8 +451,17 @@ pub struct SessionStatus { pub total_output_tokens: i64, // Cost tracking - /// Accumulated session cost in USD as a decimal string (e.g., "0.047832"). - /// None means rate data was unavailable — not zero cost. + /// Accumulated session cost in USD stored as a high-precision decimal string + /// (e.g., "0.047832"). None means rate data was unavailable — not zero cost. + /// + /// Stored as String (not rust_decimal::Decimal) deliberately: + /// - The kernel does not perform arithmetic on cost — it only stores and passes it. + /// - Type enforcement (Decimal, float rejection) is the responsibility of the + /// Python layer where cost enters and exits the system. + /// - Avoids a rust_decimal dependency in the kernel for a transport-only field. + /// + /// If cost arithmetic is ever needed inside the kernel, change this type to + /// rust_decimal::Decimal and add the rust_decimal crate to Cargo.toml. #[serde(default, skip_serializing_if = "Option::is_none")] pub cost_usd: Option, From a078b42caaf40bb1bd8341f40d4e8e609f53318d Mon Sep 17 00:00:00 2001 From: Ken Chau Date: Mon, 4 May 2026 21:23:04 -0700 Subject: [PATCH 10/11] =?UTF-8?q?style:=20cargo=20fmt=20=E2=80=94=20split?= =?UTF-8?q?=20long=20string=20literal=20in=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rustfmt CI requires lines under the column limit. The long raw string in session_status_cost_usd_roundtrip was split across two lines to satisfy the formatter. --- crates/amplifier-core/src/models.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/amplifier-core/src/models.rs b/crates/amplifier-core/src/models.rs index b790c679..266c62e7 100644 --- a/crates/amplifier-core/src/models.rs +++ b/crates/amplifier-core/src/models.rs @@ -900,7 +900,8 @@ mod tests { fn session_status_cost_usd_roundtrip() { // Verifies cost_usd: Option is present and roundtrips correctly. // String type matches Decimal JSON serialization on the Python side. - let json = r#"{"session_id": "s1", "started_at": "2025-01-01T00:00:00Z", "cost_usd": "0.047832"}"#; + let json = + r#"{"session_id": "s1", "started_at": "2025-01-01T00:00:00Z", "cost_usd": "0.047832"}"#; let status: SessionStatus = serde_json::from_str(json).unwrap(); assert_eq!(status.cost_usd, Some("0.047832".to_string())); From ac6bf9fde50f74574a3441ee4361712624a04422 Mon Sep 17 00:00:00 2001 From: Ken Chau Date: Tue, 5 May 2026 13:16:58 -0700 Subject: [PATCH 11/11] fix: split proto cleanup to #71; fix bump_version.py __init__.py coverage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - proto/amplifier_module_pb2.py and proto/test_task03_module_specific.py reverted to main state — the protoc header bump (6.31.1→6.33.2) and the Task03 TDD script deletion are unrelated to cost_usd and have been split to PR #71 so each diff is reviewable on its own merits. - scripts/bump_version.py: add python/amplifier_core/__init__.py to VERSION_FILES and extend VERSION_LINE_RE to match `__version__ = "X.Y.Z"` (was matching only `version = "X.Y.Z"`). This was the root cause of the 1.0.7 version lag on main — the bump script didn't cover __init__.py. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com> --- proto/amplifier_module_pb2.py | 6 +- proto/test_task03_module_specific.py | 239 +++++++++++++++++++++++++++ scripts/bump_version.py | 3 +- 3 files changed, 244 insertions(+), 4 deletions(-) create mode 100644 proto/test_task03_module_specific.py diff --git a/proto/amplifier_module_pb2.py b/proto/amplifier_module_pb2.py index d4acf8db..6f4d7515 100644 --- a/proto/amplifier_module_pb2.py +++ b/proto/amplifier_module_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: amplifier_module.proto -# Protobuf Python Version: 6.33.2 +# Protobuf Python Version: 6.31.1 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -12,8 +12,8 @@ _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, 6, - 33, - 2, + 31, + 1, '', 'amplifier_module.proto' ) diff --git a/proto/test_task03_module_specific.py b/proto/test_task03_module_specific.py new file mode 100644 index 00000000..80c7b8b6 --- /dev/null +++ b/proto/test_task03_module_specific.py @@ -0,0 +1,239 @@ +"""TDD test for Task 03: Module-specific messages in amplifier_module.proto. + +Tests proto compilation and verifies all required types are present. +""" +import subprocess +import re +import sys +import os +import tempfile + +PROTO_PATH = os.path.join(os.path.dirname(__file__), "amplifier_module.proto") + + +def read_proto(): + with open(PROTO_PATH, "r") as f: + return f.read() + + +def field_present(body, field_spec): + """Check if a field like 'bool success' is present, tolerating extra whitespace.""" + # Split field_spec into parts and join with \s+ for flexible matching + parts = field_spec.split() + pattern = r'\s+'.join(re.escape(p) for p in parts) + return bool(re.search(pattern, body)) + + +def test_proto_compiles(): + """Proto must compile with exit code 0.""" + with tempfile.TemporaryDirectory() as tmpdir: + result = subprocess.run( + ["protoc", f"--proto_path={os.path.dirname(PROTO_PATH)}", + f"--python_out={tmpdir}", PROTO_PATH], + capture_output=True, text=True + ) + assert result.returncode == 0, f"protoc failed:\n{result.stderr}" + + +# --------------------------------------------------------------------------- +# Enums +# --------------------------------------------------------------------------- + +def test_hook_action_enum(): + """HookAction enum with 6 values: UNSPECIFIED through ASK_USER.""" + content = read_proto() + assert "enum HookAction" in content, "Missing enum HookAction" + # Extract enum body + m = re.search(r'enum HookAction\s*\{([^}]+)\}', content) + assert m, "Cannot parse HookAction enum body" + body = m.group(1) + expected = [ + "HOOK_ACTION_UNSPECIFIED", + "HOOK_ACTION_CONTINUE", + "HOOK_ACTION_MODIFY", + "HOOK_ACTION_SKIP", + "HOOK_ACTION_BLOCK", + "HOOK_ACTION_ASK_USER", + ] + for val in expected: + assert val in body, f"HookAction missing value: {val}" + + +def test_context_injection_role_enum(): + """ContextInjectionRole enum with 4 values.""" + content = read_proto() + assert "enum ContextInjectionRole" in content, "Missing enum ContextInjectionRole" + m = re.search(r'enum ContextInjectionRole\s*\{([^}]+)\}', content) + assert m, "Cannot parse ContextInjectionRole enum body" + body = m.group(1) + expected = [ + "CONTEXT_INJECTION_ROLE_UNSPECIFIED", + "CONTEXT_INJECTION_ROLE_SYSTEM", + "CONTEXT_INJECTION_ROLE_USER", + "CONTEXT_INJECTION_ROLE_ASSISTANT", + ] + for val in expected: + assert val in body, f"ContextInjectionRole missing value: {val}" + + +def test_approval_default_enum(): + """ApprovalDefault enum with 3 values.""" + content = read_proto() + assert "enum ApprovalDefault" in content, "Missing enum ApprovalDefault" + m = re.search(r'enum ApprovalDefault\s*\{([^}]+)\}', content) + assert m, "Cannot parse ApprovalDefault enum body" + body = m.group(1) + expected = [ + "APPROVAL_DEFAULT_UNSPECIFIED", + "APPROVAL_DEFAULT_APPROVE", + "APPROVAL_DEFAULT_DENY", + ] + for val in expected: + assert val in body, f"ApprovalDefault missing value: {val}" + + +def test_user_message_level_enum(): + """UserMessageLevel enum with 4 values.""" + content = read_proto() + assert "enum UserMessageLevel" in content, "Missing enum UserMessageLevel" + m = re.search(r'enum UserMessageLevel\s*\{([^}]+)\}', content) + assert m, "Cannot parse UserMessageLevel enum body" + body = m.group(1) + expected = [ + "USER_MESSAGE_LEVEL_UNSPECIFIED", + "USER_MESSAGE_LEVEL_INFO", + "USER_MESSAGE_LEVEL_WARNING", + "USER_MESSAGE_LEVEL_ERROR", + ] + for val in expected: + assert val in body, f"UserMessageLevel missing value: {val}" + + +# --------------------------------------------------------------------------- +# Messages +# --------------------------------------------------------------------------- + +def test_tool_result_message(): + """ToolResult message with 3 fields: success, output_json, error_json.""" + content = read_proto() + assert "message ToolResult" in content, "Missing message ToolResult" + m = re.search(r'message ToolResult\s*\{([^}]+)\}', content) + assert m, "Cannot parse ToolResult body" + body = m.group(1) + assert field_present(body, "bool success"), "ToolResult missing field: success" + assert field_present(body, "string output_json"), "ToolResult missing field: output_json" + assert field_present(body, "string error_json"), "ToolResult missing field: error_json" + + +def test_hook_result_message_15_fields(): + """HookResult must have all 15 fields.""" + content = read_proto() + assert "message HookResult" in content, "Missing message HookResult" + m = re.search(r'message HookResult\s*\{([^}]+)\}', content) + assert m, "Cannot parse HookResult body" + body = m.group(1) + expected_fields = [ + "HookAction action", + "string data_json", + "string reason", + "string context_injection", + "ContextInjectionRole context_injection_role", + "bool ephemeral", + "string approval_prompt", + "repeated string approval_options", + "double approval_timeout", + "ApprovalDefault approval_default", + "bool suppress_output", + "string user_message", + "UserMessageLevel user_message_level", + "string user_message_source", + "bool append_to_last_tool_result", + ] + for field in expected_fields: + assert field_present(body, field), f"HookResult missing field: {field}" + # Verify approval_timeout default is 300.0 + # proto3 doesn't support default values natively; check for a comment + assert "300" in body, "HookResult: approval_timeout should reference default 300" + + +def test_model_info_message(): + """ModelInfo message with 6 fields.""" + content = read_proto() + assert "message ModelInfo" in content, "Missing message ModelInfo" + m = re.search(r'message ModelInfo\s*\{([^}]+)\}', content) + assert m, "Cannot parse ModelInfo body" + body = m.group(1) + expected_fields = [ + "string id", + "string display_name", + "int32 context_window", + "int32 max_output_tokens", + "repeated string capabilities", + "string defaults_json", + ] + for field in expected_fields: + assert field_present(body, field), f"ModelInfo missing field: {field}" + + +def test_provider_info_message(): + """ProviderInfo message with 6 fields including config_fields.""" + content = read_proto() + assert "message ProviderInfo" in content, "Missing message ProviderInfo" + m = re.search(r'message ProviderInfo\s*\{([^}]+)\}', content) + assert m, "Cannot parse ProviderInfo body" + body = m.group(1) + assert "config_fields" in body, "ProviderInfo missing field: config_fields" + # Count fields (lines with field numbers) + field_numbers = re.findall(r'=\s*\d+', body) + assert len(field_numbers) >= 6, f"ProviderInfo should have >= 6 fields, found {len(field_numbers)}" + + +def test_approval_request_message(): + """ApprovalRequest with 5 fields: tool_name, action, details_json, risk_level, timeout.""" + content = read_proto() + assert "message ApprovalRequest" in content, "Missing message ApprovalRequest" + m = re.search(r'message ApprovalRequest\s*\{([^}]+)\}', content) + assert m, "Cannot parse ApprovalRequest body" + body = m.group(1) + expected_fields = [ + "string tool_name", + "string action", + "string details_json", + "string risk_level", + "double timeout", + ] + for field in expected_fields: + assert field_present(body, field), f"ApprovalRequest missing field: {field}" + + +def test_approval_response_message(): + """ApprovalResponse with 3 fields: approved, reason, remember.""" + content = read_proto() + assert "message ApprovalResponse" in content, "Missing message ApprovalResponse" + m = re.search(r'message ApprovalResponse\s*\{([^}]+)\}', content) + assert m, "Cannot parse ApprovalResponse body" + body = m.group(1) + expected_fields = [ + "bool approved", + "string reason", + "bool remember", + ] + for field in expected_fields: + assert field_present(body, field), f"ApprovalResponse missing field: {field}" + + +if __name__ == "__main__": + # Run all test functions + failed = [] + passed = [] + for name, obj in sorted(globals().items()): + if name.startswith("test_") and callable(obj): + try: + obj() + passed.append(name) + print(f" PASS: {name}") + except AssertionError as e: + failed.append((name, str(e))) + print(f" FAIL: {name} -> {e}") + print(f"\n{len(passed)} passed, {len(failed)} failed") + sys.exit(1 if failed else 0) diff --git a/scripts/bump_version.py b/scripts/bump_version.py index ee31b1b7..3249896e 100644 --- a/scripts/bump_version.py +++ b/scripts/bump_version.py @@ -29,10 +29,11 @@ ("pyproject.toml", 3), ("crates/amplifier-core/Cargo.toml", 3), ("bindings/python/Cargo.toml", 3), + ("python/amplifier_core/__init__.py", 9), ] SEMVER_RE = re.compile(r"^\d+\.\d+\.\d+$") -VERSION_LINE_RE = re.compile(r'^(version\s*=\s*")([^"]+)(")', re.MULTILINE) +VERSION_LINE_RE = re.compile(r'^((?:__)?version\s*=\s*")([^"]+)(")', re.MULTILINE) def die(msg: str) -> NoReturn: