diff --git a/.repository-projection.json b/.repository-projection.json index bc666a3..6127f54 100644 --- a/.repository-projection.json +++ b/.repository-projection.json @@ -3,11 +3,11 @@ "projection": "deixic-python", "projectionSchemaVersion": 1, "sourceRepository": "dx-corp/mono", - "sourceSha": "6878323651fdb771b8cbf76b08597b930938ce36", + "sourceSha": "d7caa65707209a2fce2e960f30618360e4ec7c74", "destinationRepository": "dx-corp/deixic-python", - "priorProjectedBase": "1a71e41b4d48efd28d8b3efdccaf714758784873", + "priorProjectedBase": "adf4c06109779a8df27bf8808499194a28e8d3b1", "definitionDigest": "b278f71b9fce8cc8d4cfbe22eff3e054ef8a20caa2142f7f6a3d54005ee55119", - "toolDigest": "16fcaea2f0e7e35de09bcd8e515d915f65cdf1eb13033eaf2845f60eaa9e0a4f", - "contentDigest": "2d91766f58c81be8dd6c7a6181bdfa231c7c73a38195603bde98eba5c948b7cc", + "toolDigest": "9f3ee17d06ac34337873740d0109c3274bff8315d312227eb55383c5d169116d", + "contentDigest": "0c5d9293e58524e921228e3ce055669ec6d19e995c722a7612bbf303634650a6", "publicationEligible": true } diff --git a/CHANGELOG.md b/CHANGELOG.md index ce9b8a8..be02039 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,35 @@ ## Unreleased +- Report missing or removed model routes during setup instead of declaring the + workspace accessible, and preserve plain-text account briefs when account + names contain structured-output instruction text. Keep rejected credential + refreshes from poisoning later requests. - Add validated, source-linked account briefs, missing-data handling, progress output, explicit owner-authorized approvals/denials, and receipt outcomes. - Verify clean package consumers over binary HTTP with killed workers, storage failures, lost responses and Python/TypeScript checkpoint interoperability. - Atomically publish and sync private checkpoint files before submission. +## [0.1.5](https://github.com/dx-corp/mono/compare/sdk/deixic/python/v0.1.4...sdk/deixic/python/v0.1.5) (2026-09-19) + + +### Bug Fixes + +* **sdk:** reject truncated Python watch streams ([#9714](https://github.com/dx-corp/mono/issues/9714)) ([76c1086](https://github.com/dx-corp/mono/commit/76c1086609a13612cda320622d48b9a5e9eb4f43)) + + +### Tests + +* **sdk:** cover empty and errored stream endings ([#9716](https://github.com/dx-corp/mono/issues/9716)) ([3482008](https://github.com/dx-corp/mono/commit/3482008754041a7adc9fcaa61eb96f75f8333589)) + +## [0.1.4](https://github.com/dx-corp/mono/compare/sdk/deixic/python/v0.1.3...sdk/deixic/python/v0.1.4) (2026-09-19) + + +### Bug Fixes + +* **sdk:** harden setup and credential recovery ([#9671](https://github.com/dx-corp/mono/issues/9671)) ([e70ec36](https://github.com/dx-corp/mono/commit/e70ec364d1ebb2669b104ab6e8aee2a2aee57986)) + ## [0.1.3](https://github.com/dx-corp/mono/compare/sdk/deixic/python/v0.1.2...sdk/deixic/python/v0.1.3) (2026-09-19) diff --git a/pyproject.toml b/pyproject.toml index 03e1752..0ee979a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "deixic-sdk" -version = "0.1.3" +version = "0.1.5" description = "Python SDK for submitting Deixic tasks, following progress, and resolving approvals" readme = "README.md" requires-python = ">=3.10" diff --git a/src/deixic/auth.py b/src/deixic/auth.py index c3e2e58..b9c74d1 100644 --- a/src/deixic/auth.py +++ b/src/deixic/auth.py @@ -89,11 +89,6 @@ def check(self, credential: Credential) -> Credential: raise authentication_error( "credential refresh removed its declared workspace_id" ) - self._declared_organization = self._declared_organization or bool( - organization_id - ) - self._declared_workspace = self._declared_workspace or bool(workspace_id) - subject = _clean(credential.subject) if self._subject and not subject: raise authentication_error( @@ -103,9 +98,6 @@ def check(self, credential: Credential) -> Credential: raise authentication_error( "credential refresh changed the authenticated subject" ) - if subject: - self._subject = subject - scopes = frozenset( scope.strip() for scope in credential.scopes if scope.strip() ) @@ -117,6 +109,15 @@ def check(self, credential: Credential) -> Credential: raise authentication_error( "credential refresh changed its declared OAuth scopes" ) + # Commit identity metadata only after every claim has passed. A rejected + # refresh must not make the original credential look as if it removed a + # tenant declaration, subject, or scope on the next request. + self._declared_organization = self._declared_organization or bool( + organization_id + ) + self._declared_workspace = self._declared_workspace or bool(workspace_id) + if subject: + self._subject = subject if scopes and self._scopes is None: self._scopes = scopes return credential diff --git a/src/deixic/client.py b/src/deixic/client.py index 6941074..c8da4cc 100644 --- a/src/deixic/client.py +++ b/src/deixic/client.py @@ -410,10 +410,16 @@ def _decode_stream( ) -> Iterator[MessageT]: def messages() -> Iterator[MessageT]: buffer = bytearray() + ended = False try: for chunk in response.iter_content(chunk_size=64 * 1024): if not chunk: continue + if ended: + raise DeixicError( + "Deixic stream returned bytes after its end envelope", + kind="protocol", + ) buffer.extend(chunk) while len(buffer) >= 5: flags = buffer[0] @@ -429,17 +435,31 @@ def messages() -> Iterator[MessageT]: del buffer[: 5 + length] if flags == 0x02: try: - document = ( - json.loads(payload.decode("utf-8")) if payload else {} - ) + document = json.loads(payload.decode("utf-8")) except (UnicodeDecodeError, json.JSONDecodeError) as exc: raise DeixicError( "Deixic stream returned an invalid end envelope", kind="protocol", ) from exc - if isinstance(document, dict) and document.get("error"): + if not isinstance(document, dict): + raise DeixicError( + "Deixic stream returned a non-object end envelope", + kind="protocol", + ) + if "error" in document: + if not isinstance(document["error"], dict): + raise DeixicError( + "Deixic stream returned an invalid error envelope", + kind="protocol", + ) raise connect_stream_error(payload, response.headers) - return + if buffer: + raise DeixicError( + "Deixic stream returned bytes after its end envelope", + kind="protocol", + ) + ended = True + break if flags != 0: raise DeixicError( f"Deixic stream used unsupported envelope flags: {flags}", @@ -458,6 +478,10 @@ def messages() -> Iterator[MessageT]: raise DeixicError( "Deixic stream ended with an incomplete frame", kind="protocol" ) + if not ended: + raise DeixicError( + "Deixic stream ended without an end envelope", kind="protocol" + ) except DeixicError: raise except Exception as exc: diff --git a/src/deixic/examples/account_brief.py b/src/deixic/examples/account_brief.py index c877444..4fc342e 100644 --- a/src/deixic/examples/account_brief.py +++ b/src/deixic/examples/account_brief.py @@ -189,7 +189,9 @@ def progress(event): ) outcome = task.wait(timeout=args.timeout, on_event=progress) - structured = FORMAT_INSTRUCTION in task.checkpoint()["body"] + # The instruction is an application-owned suffix. An account name + # containing the same text must not change the saved request mode. + structured = task.checkpoint()["body"].endswith(FORMAT_INSTRUCTION) brief = None if outcome.status == "completed" and structured: try: diff --git a/src/deixic/tasks.py b/src/deixic/tasks.py index 5ddfffa..2724050 100644 --- a/src/deixic/tasks.py +++ b/src/deixic/tasks.py @@ -205,7 +205,10 @@ def check_setup(self, *, channel_id: str) -> SetupCheck: ), None, ) - unavailable_model = selected is not None and not selected.ready + # Platform deliberately omits both the catalog and default target when + # managed inference is unavailable. An explicit selection that no + # longer appears in the catalog is unavailable for the same reason. + unavailable_model = selected is None or not selected.ready return SetupCheck( "needs_attention" if missing or unavailable_model else "accessible", channel_id, diff --git a/src/memory/v1/memory_pb2.py b/src/memory/v1/memory_pb2.py index 0d18183..3748647 100644 --- a/src/memory/v1/memory_pb2.py +++ b/src/memory/v1/memory_pb2.py @@ -28,7 +28,7 @@ from evalops_platform.v1 import platform_pb2 as platform_dot_v1_dot_platform__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16memory/v1/memory.proto\x12\tmemory.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x15\x63ommon/v1/authz.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1aplatform/v1/platform.proto\"\x8d\x02\n\x0fSourceReference\x12\x10\n\x03uri\x18\x01 \x01(\tR\x03uri\x12\x14\n\x05title\x18\x02 \x01(\tR\x05title\x12\x12\n\x04type\x18\x03 \x01(\tR\x04type\x12\x44\n\x08metadata\x18\x04 \x03(\x0b\x32(.memory.v1.SourceReference.MetadataEntryR\x08metadata\x12;\n\x0cresource_ref\x18\x05 \x01(\x0b\x32\x18.platform.v1.ResourceRefR\x0bresourceRef\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xcc\x08\n\x06Memory\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12&\n\x05scope\x18\x02 \x01(\x0e\x32\x10.memory.v1.ScopeR\x05scope\x12\x18\n\x07\x63ontent\x18\x03 \x01(\tR\x07\x63ontent\x12\x12\n\x04type\x18\x04 \x01(\tR\x04type\x12\x16\n\x06source\x18\x05 \x01(\tR\x06source\x12\x1e\n\nconfidence\x18\x06 \x01(\x02R\nconfidence\x12\x16\n\x06pinned\x18\x07 \x01(\x08R\x06pinned\x12 \n\tembedding\x18\x08 \x03(\x02\x42\x02\x10\x01R\tembedding\x12!\n\x0cworkspace_id\x18\t \x01(\tR\x0bworkspaceId\x12\x17\n\x07user_id\x18\n \x01(\tR\x06userId\x12\x1d\n\nproject_id\x18\x0b \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x0c \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\r \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\x0e \x01(\tR\x05\x61gent\x12\x1b\n\tis_policy\x18\x0f \x01(\x08R\x08isPolicy\x12\x39\n\ncreated_at\x18\x10 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x39\n\nupdated_at\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12\x12\n\x04tags\x18\x12 \x03(\tR\x04tags\x12\x19\n\x08\x61gent_id\x18\x13 \x01(\tR\x07\x61gentId\x12G\n\x11source_references\x18\x14 \x03(\x0b\x32\x1a.memory.v1.SourceReferenceR\x10sourceReferences\x12\x39\n\nexpires_at\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\texpiresAt\x12\x30\n\x14supersedes_memory_id\x18\x16 \x01(\tR\x12supersedesMemoryId\x12\x35\n\x17superseded_by_memory_id\x18\x17 \x01(\tR\x14supersededByMemoryId\x12\x42\n\rreview_status\x18\x18 \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\x12\x1f\n\x0bproposed_by\x18\x19 \x01(\tR\nproposedBy\x12\'\n\x0fproposal_reason\x18\x1a \x01(\tR\x0eproposalReason\x12\x1d\n\nentity_ids\x18\x1b \x03(\tR\tentityIds\x12\x1a\n\x08revision\x18\x1c \x01(\x03R\x08revision\x12H\n\x0flifecycle_state\x18\x1d \x01(\x0e\x32\x1f.memory.v1.MemoryLifecycleStateR\x0elifecycleState\"\xf3\x03\n\x14MemoryLifecycleEvent\x12\x19\n\x08\x65vent_id\x18\x01 \x01(\tR\x07\x65ventId\x12\x1b\n\tmemory_id\x18\x02 \x01(\tR\x08memoryId\x12\x1a\n\x08revision\x18\x03 \x01(\x03R\x08revision\x12\x42\n\nevent_type\x18\x04 \x01(\x0e\x32#.memory.v1.MemoryLifecycleEventTypeR\teventType\x12\x36\n\x17previous_content_digest\x18\x05 \x01(\tR\x15previousContentDigest\x12%\n\x0e\x63ontent_digest\x18\x06 \x01(\tR\rcontentDigest\x12\x19\n\x08\x61\x63tor_id\x18\x07 \x01(\tR\x07\x61\x63torId\x12\x1d\n\npolicy_ref\x18\x08 \x01(\tR\tpolicyRef\x12%\n\x0eprovenance_ref\x18\t \x01(\tR\rprovenanceRef\x12\x1d\n\nuse_reason\x18\n \x01(\tR\tuseReason\x12\'\n\x0fidempotency_key\x18\x0b \x01(\tR\x0eidempotencyKey\x12;\n\x0brecorded_at\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nrecordedAt\"\xc3\x03\n\x12MemoryRelationship\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12(\n\x10source_memory_id\x18\x02 \x01(\tR\x0esourceMemoryId\x12(\n\x10target_memory_id\x18\x03 \x01(\tR\x0etargetMemoryId\x12\x12\n\x04type\x18\x04 \x01(\tR\x04type\x12\x1e\n\nconfidence\x18\x05 \x01(\x02R\nconfidence\x12\x39\n\nvalid_from\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tvalidFrom\x12;\n\x0bvalid_until\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nvalidUntil\x12\x39\n\ncreated_at\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x39\n\nupdated_at\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12\'\n\x0forganization_id\x18\n \x01(\tR\x0eorganizationId\"\x96\x06\n\x0cStoreRequest\x12\x30\n\x05scope\x18\x01 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12!\n\x07\x63ontent\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x07\x63ontent\x12\x1b\n\x04type\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04type\x12\x16\n\x06source\x18\x04 \x01(\tR\x06source\x12\x1e\n\nconfidence\x18\x05 \x01(\x02R\nconfidence\x12\x1d\n\nproject_id\x18\x06 \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x07 \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\x08 \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\t \x01(\tR\x05\x61gent\x12\x1b\n\tis_policy\x18\n \x01(\x08R\x08isPolicy\x12\x12\n\x04tags\x18\x0b \x03(\tR\x04tags\x12\x0e\n\x02id\x18\x0c \x01(\tR\x02id\x12\x19\n\x08\x61gent_id\x18\r \x01(\tR\x07\x61gentId\x12\x17\n\x07user_id\x18\x0e \x01(\tR\x06userId\x12\x16\n\x06pinned\x18\x0f \x01(\x08R\x06pinned\x12G\n\x11source_references\x18\x10 \x03(\x0b\x32\x1a.memory.v1.SourceReferenceR\x10sourceReferences\x12\x39\n\nexpires_at\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\texpiresAt\x12\x30\n\x14supersedes_memory_id\x18\x12 \x01(\tR\x12supersedesMemoryId\x12\x42\n\rreview_status\x18\x13 \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\x12\x1f\n\x0bproposed_by\x18\x14 \x01(\tR\nproposedBy\x12\'\n\x0fproposal_reason\x18\x15 \x01(\tR\x0eproposalReason\x12\x1d\n\nentity_ids\x18\x16 \x03(\tR\tentityIds\":\n\rStoreResponse\x12)\n\x06memory\x18\x01 \x01(\x0b\x32\x11.memory.v1.MemoryR\x06memory\"~\n\x11StoreBatchRequest\x12=\n\x08memories\x18\x01 \x03(\x0b\x32\x17.memory.v1.StoreRequestB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x08memories\x12*\n\x11\x63ontinue_on_error\x18\x02 \x01(\x08R\x0f\x63ontinueOnError\"K\n\x12StoreBatchResponse\x12\x35\n\x07results\x18\x01 \x03(\x0b\x32\x1b.memory.v1.StoreBatchResultR\x07results\"i\n\x10StoreBatchResult\x12\x14\n\x05index\x18\x01 \x01(\x05R\x05index\x12)\n\x06memory\x18\x02 \x01(\x0b\x32\x11.memory.v1.MemoryR\x06memory\x12\x14\n\x05\x65rror\x18\x03 \x01(\tR\x05\x65rror\"\xcd\x04\n\rRecallRequest\x12\x14\n\x05query\x18\x01 \x01(\tR\x05query\x12\x30\n\x05scope\x18\x02 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12\x1c\n\x05top_k\x18\x03 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x04topK\x12%\n\x0emin_similarity\x18\x04 \x01(\x02R\rminSimilarity\x12\x1d\n\nproject_id\x18\x05 \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x06 \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\x07 \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\x08 \x01(\tR\x05\x61gent\x12\x12\n\x04type\x18\t \x01(\tR\x04type\x12\x19\n\x08\x61gent_id\x18\n \x01(\tR\x07\x61gentId\x12\x17\n\x07user_id\x18\x0b \x01(\tR\x06userId\x12\x42\n\rreview_status\x18\x0c \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\x12\x1d\n\nentity_ids\x18\r \x03(\tR\tentityIds\x12\x36\n\x12relationship_depth\x18\x0e \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x11relationshipDepth\x12-\n\x12relationship_types\x18\x0f \x03(\tR\x11relationshipTypes\x12/\n\x05\x61s_of\x18\x10 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x04\x61sOf\"\xee\x02\n\x16RecallKnowledgeRequest\x12\x1e\n\nconditions\x18\x01 \x03(\tR\nconditions\x12\x30\n\x05scope\x18\x02 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12\x1c\n\x05top_k\x18\x03 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x04topK\x12\x1d\n\nproject_id\x18\x04 \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x05 \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\x06 \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\x07 \x01(\tR\x05\x61gent\x12\x19\n\x08\x61gent_id\x18\x08 \x01(\tR\x07\x61gentId\x12\x17\n\x07user_id\x18\t \x01(\tR\x06userId\x12\x42\n\rreview_status\x18\n \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\"+\n\x10GetMemoryRequest\x12\x17\n\x02id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x02id\">\n\x11GetMemoryResponse\x12)\n\x06memory\x18\x01 \x01(\x0b\x32\x11.memory.v1.MemoryR\x06memory\"/\n\x14\x45xplainMemoryRequest\x12\x17\n\x02id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x02id\"P\n\x15\x45xplainMemoryResponse\x12\x37\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x1f.memory.v1.MemoryLifecycleEventR\x06\x65vents\"C\n\x0eRecallResponse\x12\x31\n\x07results\x18\x01 \x03(\x0b\x32\x17.memory.v1.RecallResultR\x07results\"L\n\x17RecallKnowledgeResponse\x12\x31\n\x07results\x18\x01 \x03(\x0b\x32\x17.memory.v1.RecallResultR\x07results\"\xcc\x03\n\x16\x43lusterMemoriesRequest\x12\x30\n\x05scope\x18\x01 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12\x1d\n\nproject_id\x18\x02 \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x03 \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\x04 \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\x05 \x01(\tR\x05\x61gent\x12\x12\n\x04type\x18\x06 \x01(\tR\x04type\x12\x19\n\x08\x61gent_id\x18\x07 \x01(\tR\x07\x61gentId\x12\x17\n\x07user_id\x18\x08 \x01(\tR\x06userId\x12\x42\n\rreview_status\x18\t \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\x12*\n\x0cmax_clusters\x18\n \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x0bmaxClusters\x12\x33\n\x11limit_per_cluster\x18\x0b \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x0flimitPerCluster\x12%\n\x0emin_similarity\x18\x0c \x01(\x02R\rminSimilarity\"O\n\x17\x43lusterMemoriesResponse\x12\x34\n\x08\x63lusters\x18\x01 \x03(\x0b\x32\x18.memory.v1.MemoryClusterR\x08\x63lusters\"\xa8\x01\n\rMemoryCluster\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n\x05topic\x18\x02 \x01(\tR\x05topic\x12\x31\n\x07results\x18\x03 \x03(\x0b\x32\x17.memory.v1.RecallResultR\x07results\x12\x1e\n\x08\x63\x65ntroid\x18\x04 \x03(\x02\x42\x02\x10\x01R\x08\x63\x65ntroid\x12\x1e\n\nsimilarity\x18\x05 \x01(\x02R\nsimilarity\"\xcc\x01\n\x0cRecallResult\x12)\n\x06memory\x18\x01 \x01(\x0b\x32\x11.memory.v1.MemoryR\x06memory\x12\x1e\n\nsimilarity\x18\x02 \x01(\x02R\nsimilarity\x12%\n\x0egraph_distance\x18\x03 \x01(\x05R\rgraphDistance\x12J\n\x11relationship_path\x18\x04 \x03(\x0b\x32\x1d.memory.v1.MemoryRelationshipR\x10relationshipPath\"\x82\x06\n\rUpdateRequest\x12\x17\n\x02id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x02id\x12\x18\n\x07\x63ontent\x18\x02 \x01(\tR\x07\x63ontent\x12\x12\n\x04type\x18\x03 \x01(\tR\x04type\x12\x1e\n\nconfidence\x18\x04 \x01(\x02R\nconfidence\x12\x12\n\x04tags\x18\x05 \x03(\tR\x04tags\x12\x16\n\x06source\x18\x06 \x01(\tR\x06source\x12\x16\n\x06pinned\x18\x07 \x01(\x08R\x06pinned\x12\x1b\n\tis_policy\x18\x08 \x01(\x08R\x08isPolicy\x12G\n\x11source_references\x18\t \x03(\x0b\x32\x1a.memory.v1.SourceReferenceR\x10sourceReferences\x12\x39\n\nexpires_at\x18\n \x01(\x0b\x32\x1a.google.protobuf.TimestampR\texpiresAt\x12\x42\n\rreview_status\x18\x0b \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\x12\x1f\n\x0bproposed_by\x18\x0c \x01(\tR\nproposedBy\x12\'\n\x0fproposal_reason\x18\r \x01(\tR\x0eproposalReason\x12\x1d\n\nentity_ids\x18\x0e \x03(\tR\tentityIds\x12\x39\n\x11\x65xpected_revision\x18\x0f \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01H\x00R\x10\x65xpectedRevision\x88\x01\x01\x12\'\n\x0fidempotency_key\x18\x10 \x01(\tR\x0eidempotencyKey\x12\x19\n\x08\x61\x63tor_id\x18\x11 \x01(\tR\x07\x61\x63torId\x12\x1d\n\npolicy_ref\x18\x12 \x01(\tR\tpolicyRef\x12%\n\x0eprovenance_ref\x18\x13 \x01(\tR\rprovenanceRef\x12\x1d\n\nuse_reason\x18\x14 \x01(\tR\tuseReasonB\x14\n\x12_expected_revision\";\n\x0eUpdateResponse\x12)\n\x06memory\x18\x01 \x01(\x0b\x32\x11.memory.v1.MemoryR\x06memory\"\xa2\x02\n\rDeleteRequest\x12\x17\n\x02id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x02id\x12\x39\n\x11\x65xpected_revision\x18\x02 \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01H\x00R\x10\x65xpectedRevision\x88\x01\x01\x12\'\n\x0fidempotency_key\x18\x03 \x01(\tR\x0eidempotencyKey\x12\x19\n\x08\x61\x63tor_id\x18\x04 \x01(\tR\x07\x61\x63torId\x12\x1d\n\npolicy_ref\x18\x05 \x01(\tR\tpolicyRef\x12%\n\x0eprovenance_ref\x18\x06 \x01(\tR\rprovenanceRef\x12\x1d\n\nuse_reason\x18\x07 \x01(\tR\tuseReasonB\x14\n\x12_expected_revision\"\x10\n\x0e\x44\x65leteResponse\"\xd5\x03\n\x0bListRequest\x12\x30\n\x05scope\x18\x01 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12\x1d\n\nproject_id\x18\x02 \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x03 \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\x04 \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\x05 \x01(\tR\x05\x61gent\x12\x1d\n\x05limit\x18\x06 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x05limit\x12\x1f\n\x06offset\x18\x07 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x06offset\x12\x12\n\x04type\x18\x08 \x01(\tR\x04type\x12\x19\n\x08\x61gent_id\x18\t \x01(\tR\x07\x61gentId\x12\x17\n\x07user_id\x18\n \x01(\tR\x06userId\x12\x42\n\rreview_status\x18\x0b \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\x12\x1d\n\nentity_ids\x18\x0c \x03(\tR\tentityIds\x12\x16\n\x06source\x18\r \x01(\tR\x06source\x12#\n\rsource_prefix\x18\x0e \x01(\tR\x0csourcePrefix\"\xc0\x02\n\x13LinkMemoriesRequest\x12\x31\n\x10source_memory_id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x0esourceMemoryId\x12\x31\n\x10target_memory_id\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x0etargetMemoryId\x12\x1b\n\x04type\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04type\x12\x1e\n\nconfidence\x18\x04 \x01(\x02R\nconfidence\x12\x39\n\nvalid_from\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tvalidFrom\x12;\n\x0bvalid_until\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nvalidUntil\x12\x0e\n\x02id\x18\x07 \x01(\tR\x02id\"Y\n\x14LinkMemoriesResponse\x12\x41\n\x0crelationship\x18\x01 \x01(\x0b\x32\x1d.memory.v1.MemoryRelationshipR\x0crelationship\"\x98\x02\n\x1eListMemoryRelationshipsRequest\x12\x1b\n\tmemory_id\x18\x01 \x01(\tR\x08memoryId\x12(\n\x10source_memory_id\x18\x02 \x01(\tR\x0esourceMemoryId\x12(\n\x10target_memory_id\x18\x03 \x01(\tR\x0etargetMemoryId\x12\x14\n\x05types\x18\x04 \x03(\tR\x05types\x12/\n\x05\x61s_of\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x04\x61sOf\x12\x1d\n\x05limit\x18\x06 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x05limit\x12\x1f\n\x06offset\x18\x07 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x06offset\"\x97\x01\n\x1fListMemoryRelationshipsResponse\x12\x43\n\rrelationships\x18\x01 \x03(\x0b\x32\x1d.memory.v1.MemoryRelationshipR\rrelationships\x12\x14\n\x05total\x18\x02 \x01(\x05R\x05total\x12\x19\n\x08has_more\x18\x03 \x01(\x08R\x07hasMore\":\n\x1f\x44\x65leteMemoryRelationshipRequest\x12\x17\n\x02id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x02id\"\"\n DeleteMemoryRelationshipResponse\"\xf2\x02\n\x18GetOperatingRulesRequest\x12\x30\n\x05scope\x18\x01 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12\x1d\n\nproject_id\x18\x02 \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x03 \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\x04 \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\x05 \x01(\tR\x05\x61gent\x12\x1d\n\x05limit\x18\x06 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x05limit\x12\x1f\n\x06offset\x18\x07 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x06offset\x12\x19\n\x08\x61gent_id\x18\x08 \x01(\tR\x07\x61gentId\x12\x17\n\x07user_id\x18\t \x01(\tR\x06userId\x12\x42\n\rreview_status\x18\n \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\"n\n\x0cListResponse\x12-\n\x08memories\x18\x01 \x03(\x0b\x32\x11.memory.v1.MemoryR\x08memories\x12\x14\n\x05total\x18\x02 \x01(\x05R\x05total\x12\x19\n\x08has_more\x18\x03 \x01(\x08R\x07hasMore\"{\n\x19GetOperatingRulesResponse\x12-\n\x08memories\x18\x01 \x03(\x0b\x32\x11.memory.v1.MemoryR\x08memories\x12\x14\n\x05total\x18\x02 \x01(\x05R\x05total\x12\x19\n\x08has_more\x18\x03 \x01(\x08R\x07hasMore\"\x9e\x01\n\x12\x43onsolidateRequest\x12\x30\n\x05scope\x18\x01 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12\x1d\n\nproject_id\x18\x02 \x01(\tR\tprojectId\x12\x12\n\x04type\x18\x03 \x01(\tR\x04type\x12#\n\rsource_prefix\x18\x04 \x01(\tR\x0csourcePrefix\"E\n\x13\x43onsolidateResponse\x12\x16\n\x06merged\x18\x01 \x01(\x05R\x06merged\x12\x16\n\x06pruned\x18\x02 \x01(\x05R\x06pruned*z\n\x05Scope\x12\x15\n\x11SCOPE_UNSPECIFIED\x10\x00\x12\x0e\n\nSCOPE_USER\x10\x01\x12\x0e\n\nSCOPE_TEAM\x10\x02\x12\x16\n\x12SCOPE_ORGANIZATION\x10\x03\x12\x0f\n\x0bSCOPE_AGENT\x10\x04\x12\x11\n\rSCOPE_PROJECT\x10\x05*\xa3\x01\n\x12MemoryReviewStatus\x12$\n MEMORY_REVIEW_STATUS_UNSPECIFIED\x10\x00\x12!\n\x1dMEMORY_REVIEW_STATUS_APPROVED\x10\x01\x12!\n\x1dMEMORY_REVIEW_STATUS_PROPOSED\x10\x02\x12!\n\x1dMEMORY_REVIEW_STATUS_REJECTED\x10\x03*\x87\x01\n\x14MemoryLifecycleState\x12&\n\"MEMORY_LIFECYCLE_STATE_UNSPECIFIED\x10\x00\x12!\n\x1dMEMORY_LIFECYCLE_STATE_ACTIVE\x10\x01\x12$\n MEMORY_LIFECYCLE_STATE_FORGOTTEN\x10\x02*\xf0\x01\n\x18MemoryLifecycleEventType\x12+\n\'MEMORY_LIFECYCLE_EVENT_TYPE_UNSPECIFIED\x10\x00\x12\'\n#MEMORY_LIFECYCLE_EVENT_TYPE_CREATED\x10\x01\x12)\n%MEMORY_LIFECYCLE_EVENT_TYPE_CORRECTED\x10\x02\x12)\n%MEMORY_LIFECYCLE_EVENT_TYPE_FORGOTTEN\x10\x03\x12(\n$MEMORY_LIFECYCLE_EVENT_TYPE_REVIEWED\x10\x04\x32\xa4\x0c\n\rMemoryService\x12R\n\x05Store\x12\x17.memory.v1.StoreRequest\x1a\x18.memory.v1.StoreResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x02\x12\x61\n\nStoreBatch\x12\x1c.memory.v1.StoreBatchRequest\x1a\x1d.memory.v1.StoreBatchResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x02\x12T\n\x06Recall\x12\x18.memory.v1.RecallRequest\x1a\x19.memory.v1.RecallResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12o\n\x0fRecallKnowledge\x12!.memory.v1.RecallKnowledgeRequest\x1a\".memory.v1.RecallKnowledgeResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12]\n\tGetMemory\x12\x1b.memory.v1.GetMemoryRequest\x1a\x1c.memory.v1.GetMemoryResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12i\n\rExplainMemory\x12\x1f.memory.v1.ExplainMemoryRequest\x1a .memory.v1.ExplainMemoryResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12o\n\x0f\x43lusterMemories\x12!.memory.v1.ClusterMemoriesRequest\x1a\".memory.v1.ClusterMemoriesResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12U\n\x06Update\x12\x18.memory.v1.UpdateRequest\x1a\x19.memory.v1.UpdateResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x02\x12U\n\x06\x44\x65lete\x12\x18.memory.v1.DeleteRequest\x1a\x19.memory.v1.DeleteResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x03\x12N\n\x04List\x12\x16.memory.v1.ListRequest\x1a\x17.memory.v1.ListResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12g\n\x0cLinkMemories\x12\x1e.memory.v1.LinkMemoriesRequest\x1a\x1f.memory.v1.LinkMemoriesResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x02\x12\x87\x01\n\x17ListMemoryRelationships\x12).memory.v1.ListMemoryRelationshipsRequest\x1a*.memory.v1.ListMemoryRelationshipsResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12\x8b\x01\n\x18\x44\x65leteMemoryRelationship\x12*.memory.v1.DeleteMemoryRelationshipRequest\x1a+.memory.v1.DeleteMemoryRelationshipResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x03\x12u\n\x11GetOperatingRules\x12#.memory.v1.GetOperatingRulesRequest\x1a$.memory.v1.GetOperatingRulesResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12\x64\n\x0b\x43onsolidate\x12\x1d.memory.v1.ConsolidateRequest\x1a\x1e.memory.v1.ConsolidateResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x02\x42\x37Z5github.com/evalops/platform/gen/go/memory/v1;memoryv1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16memory/v1/memory.proto\x12\tmemory.v1\x1a\x1b\x62uf/validate/validate.proto\x1a\x15\x63ommon/v1/authz.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1aplatform/v1/platform.proto\"\x8d\x02\n\x0fSourceReference\x12\x10\n\x03uri\x18\x01 \x01(\tR\x03uri\x12\x14\n\x05title\x18\x02 \x01(\tR\x05title\x12\x12\n\x04type\x18\x03 \x01(\tR\x04type\x12\x44\n\x08metadata\x18\x04 \x03(\x0b\x32(.memory.v1.SourceReference.MetadataEntryR\x08metadata\x12;\n\x0cresource_ref\x18\x05 \x01(\x0b\x32\x18.platform.v1.ResourceRefR\x0bresourceRef\x1a;\n\rMetadataEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n\x05value\x18\x02 \x01(\tR\x05value:\x02\x38\x01\"\xcc\x08\n\x06Memory\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12&\n\x05scope\x18\x02 \x01(\x0e\x32\x10.memory.v1.ScopeR\x05scope\x12\x18\n\x07\x63ontent\x18\x03 \x01(\tR\x07\x63ontent\x12\x12\n\x04type\x18\x04 \x01(\tR\x04type\x12\x16\n\x06source\x18\x05 \x01(\tR\x06source\x12\x1e\n\nconfidence\x18\x06 \x01(\x02R\nconfidence\x12\x16\n\x06pinned\x18\x07 \x01(\x08R\x06pinned\x12 \n\tembedding\x18\x08 \x03(\x02\x42\x02\x10\x01R\tembedding\x12!\n\x0cworkspace_id\x18\t \x01(\tR\x0bworkspaceId\x12\x17\n\x07user_id\x18\n \x01(\tR\x06userId\x12\x1d\n\nproject_id\x18\x0b \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x0c \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\r \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\x0e \x01(\tR\x05\x61gent\x12\x1b\n\tis_policy\x18\x0f \x01(\x08R\x08isPolicy\x12\x39\n\ncreated_at\x18\x10 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x39\n\nupdated_at\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12\x12\n\x04tags\x18\x12 \x03(\tR\x04tags\x12\x19\n\x08\x61gent_id\x18\x13 \x01(\tR\x07\x61gentId\x12G\n\x11source_references\x18\x14 \x03(\x0b\x32\x1a.memory.v1.SourceReferenceR\x10sourceReferences\x12\x39\n\nexpires_at\x18\x15 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\texpiresAt\x12\x30\n\x14supersedes_memory_id\x18\x16 \x01(\tR\x12supersedesMemoryId\x12\x35\n\x17superseded_by_memory_id\x18\x17 \x01(\tR\x14supersededByMemoryId\x12\x42\n\rreview_status\x18\x18 \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\x12\x1f\n\x0bproposed_by\x18\x19 \x01(\tR\nproposedBy\x12\'\n\x0fproposal_reason\x18\x1a \x01(\tR\x0eproposalReason\x12\x1d\n\nentity_ids\x18\x1b \x03(\tR\tentityIds\x12\x1a\n\x08revision\x18\x1c \x01(\x03R\x08revision\x12H\n\x0flifecycle_state\x18\x1d \x01(\x0e\x32\x1f.memory.v1.MemoryLifecycleStateR\x0elifecycleState\"\xf3\x03\n\x14MemoryLifecycleEvent\x12\x19\n\x08\x65vent_id\x18\x01 \x01(\tR\x07\x65ventId\x12\x1b\n\tmemory_id\x18\x02 \x01(\tR\x08memoryId\x12\x1a\n\x08revision\x18\x03 \x01(\x03R\x08revision\x12\x42\n\nevent_type\x18\x04 \x01(\x0e\x32#.memory.v1.MemoryLifecycleEventTypeR\teventType\x12\x36\n\x17previous_content_digest\x18\x05 \x01(\tR\x15previousContentDigest\x12%\n\x0e\x63ontent_digest\x18\x06 \x01(\tR\rcontentDigest\x12\x19\n\x08\x61\x63tor_id\x18\x07 \x01(\tR\x07\x61\x63torId\x12\x1d\n\npolicy_ref\x18\x08 \x01(\tR\tpolicyRef\x12%\n\x0eprovenance_ref\x18\t \x01(\tR\rprovenanceRef\x12\x1d\n\nuse_reason\x18\n \x01(\tR\tuseReason\x12\'\n\x0fidempotency_key\x18\x0b \x01(\tR\x0eidempotencyKey\x12;\n\x0brecorded_at\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nrecordedAt\"\xc3\x03\n\x12MemoryRelationship\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12(\n\x10source_memory_id\x18\x02 \x01(\tR\x0esourceMemoryId\x12(\n\x10target_memory_id\x18\x03 \x01(\tR\x0etargetMemoryId\x12\x12\n\x04type\x18\x04 \x01(\tR\x04type\x12\x1e\n\nconfidence\x18\x05 \x01(\x02R\nconfidence\x12\x39\n\nvalid_from\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tvalidFrom\x12;\n\x0bvalid_until\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nvalidUntil\x12\x39\n\ncreated_at\x18\x08 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x39\n\nupdated_at\x18\t \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12\'\n\x0forganization_id\x18\n \x01(\tR\x0eorganizationId\"\x96\x06\n\x0cStoreRequest\x12\x30\n\x05scope\x18\x01 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12!\n\x07\x63ontent\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x07\x63ontent\x12\x1b\n\x04type\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04type\x12\x16\n\x06source\x18\x04 \x01(\tR\x06source\x12\x1e\n\nconfidence\x18\x05 \x01(\x02R\nconfidence\x12\x1d\n\nproject_id\x18\x06 \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x07 \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\x08 \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\t \x01(\tR\x05\x61gent\x12\x1b\n\tis_policy\x18\n \x01(\x08R\x08isPolicy\x12\x12\n\x04tags\x18\x0b \x03(\tR\x04tags\x12\x0e\n\x02id\x18\x0c \x01(\tR\x02id\x12\x19\n\x08\x61gent_id\x18\r \x01(\tR\x07\x61gentId\x12\x17\n\x07user_id\x18\x0e \x01(\tR\x06userId\x12\x16\n\x06pinned\x18\x0f \x01(\x08R\x06pinned\x12G\n\x11source_references\x18\x10 \x03(\x0b\x32\x1a.memory.v1.SourceReferenceR\x10sourceReferences\x12\x39\n\nexpires_at\x18\x11 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\texpiresAt\x12\x30\n\x14supersedes_memory_id\x18\x12 \x01(\tR\x12supersedesMemoryId\x12\x42\n\rreview_status\x18\x13 \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\x12\x1f\n\x0bproposed_by\x18\x14 \x01(\tR\nproposedBy\x12\'\n\x0fproposal_reason\x18\x15 \x01(\tR\x0eproposalReason\x12\x1d\n\nentity_ids\x18\x16 \x03(\tR\tentityIds\":\n\rStoreResponse\x12)\n\x06memory\x18\x01 \x01(\x0b\x32\x11.memory.v1.MemoryR\x06memory\"~\n\x11StoreBatchRequest\x12=\n\x08memories\x18\x01 \x03(\x0b\x32\x17.memory.v1.StoreRequestB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x08memories\x12*\n\x11\x63ontinue_on_error\x18\x02 \x01(\x08R\x0f\x63ontinueOnError\"K\n\x12StoreBatchResponse\x12\x35\n\x07results\x18\x01 \x03(\x0b\x32\x1b.memory.v1.StoreBatchResultR\x07results\"i\n\x10StoreBatchResult\x12\x14\n\x05index\x18\x01 \x01(\x05R\x05index\x12)\n\x06memory\x18\x02 \x01(\x0b\x32\x11.memory.v1.MemoryR\x06memory\x12\x14\n\x05\x65rror\x18\x03 \x01(\tR\x05\x65rror\"\xcd\x04\n\rRecallRequest\x12\x14\n\x05query\x18\x01 \x01(\tR\x05query\x12\x30\n\x05scope\x18\x02 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12\x1c\n\x05top_k\x18\x03 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x04topK\x12%\n\x0emin_similarity\x18\x04 \x01(\x02R\rminSimilarity\x12\x1d\n\nproject_id\x18\x05 \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x06 \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\x07 \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\x08 \x01(\tR\x05\x61gent\x12\x12\n\x04type\x18\t \x01(\tR\x04type\x12\x19\n\x08\x61gent_id\x18\n \x01(\tR\x07\x61gentId\x12\x17\n\x07user_id\x18\x0b \x01(\tR\x06userId\x12\x42\n\rreview_status\x18\x0c \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\x12\x1d\n\nentity_ids\x18\r \x03(\tR\tentityIds\x12\x36\n\x12relationship_depth\x18\x0e \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x11relationshipDepth\x12-\n\x12relationship_types\x18\x0f \x03(\tR\x11relationshipTypes\x12/\n\x05\x61s_of\x18\x10 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x04\x61sOf\"\xee\x02\n\x16RecallKnowledgeRequest\x12\x1e\n\nconditions\x18\x01 \x03(\tR\nconditions\x12\x30\n\x05scope\x18\x02 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12\x1c\n\x05top_k\x18\x03 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x04topK\x12\x1d\n\nproject_id\x18\x04 \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x05 \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\x06 \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\x07 \x01(\tR\x05\x61gent\x12\x19\n\x08\x61gent_id\x18\x08 \x01(\tR\x07\x61gentId\x12\x17\n\x07user_id\x18\t \x01(\tR\x06userId\x12\x42\n\rreview_status\x18\n \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\"+\n\x10GetMemoryRequest\x12\x17\n\x02id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x02id\">\n\x11GetMemoryResponse\x12)\n\x06memory\x18\x01 \x01(\x0b\x32\x11.memory.v1.MemoryR\x06memory\"/\n\x14\x45xplainMemoryRequest\x12\x17\n\x02id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x02id\"P\n\x15\x45xplainMemoryResponse\x12\x37\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x1f.memory.v1.MemoryLifecycleEventR\x06\x65vents\"C\n\x0eRecallResponse\x12\x31\n\x07results\x18\x01 \x03(\x0b\x32\x17.memory.v1.RecallResultR\x07results\"L\n\x17RecallKnowledgeResponse\x12\x31\n\x07results\x18\x01 \x03(\x0b\x32\x17.memory.v1.RecallResultR\x07results\"\xcc\x03\n\x16\x43lusterMemoriesRequest\x12\x30\n\x05scope\x18\x01 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12\x1d\n\nproject_id\x18\x02 \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x03 \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\x04 \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\x05 \x01(\tR\x05\x61gent\x12\x12\n\x04type\x18\x06 \x01(\tR\x04type\x12\x19\n\x08\x61gent_id\x18\x07 \x01(\tR\x07\x61gentId\x12\x17\n\x07user_id\x18\x08 \x01(\tR\x06userId\x12\x42\n\rreview_status\x18\t \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\x12*\n\x0cmax_clusters\x18\n \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x0bmaxClusters\x12\x33\n\x11limit_per_cluster\x18\x0b \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x0flimitPerCluster\x12%\n\x0emin_similarity\x18\x0c \x01(\x02R\rminSimilarity\"O\n\x17\x43lusterMemoriesResponse\x12\x34\n\x08\x63lusters\x18\x01 \x03(\x0b\x32\x18.memory.v1.MemoryClusterR\x08\x63lusters\"\xa8\x01\n\rMemoryCluster\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n\x05topic\x18\x02 \x01(\tR\x05topic\x12\x31\n\x07results\x18\x03 \x03(\x0b\x32\x17.memory.v1.RecallResultR\x07results\x12\x1e\n\x08\x63\x65ntroid\x18\x04 \x03(\x02\x42\x02\x10\x01R\x08\x63\x65ntroid\x12\x1e\n\nsimilarity\x18\x05 \x01(\x02R\nsimilarity\"\xcc\x01\n\x0cRecallResult\x12)\n\x06memory\x18\x01 \x01(\x0b\x32\x11.memory.v1.MemoryR\x06memory\x12\x1e\n\nsimilarity\x18\x02 \x01(\x02R\nsimilarity\x12%\n\x0egraph_distance\x18\x03 \x01(\x05R\rgraphDistance\x12J\n\x11relationship_path\x18\x04 \x03(\x0b\x32\x1d.memory.v1.MemoryRelationshipR\x10relationshipPath\"\x82\x06\n\rUpdateRequest\x12\x17\n\x02id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x02id\x12\x18\n\x07\x63ontent\x18\x02 \x01(\tR\x07\x63ontent\x12\x12\n\x04type\x18\x03 \x01(\tR\x04type\x12\x1e\n\nconfidence\x18\x04 \x01(\x02R\nconfidence\x12\x12\n\x04tags\x18\x05 \x03(\tR\x04tags\x12\x16\n\x06source\x18\x06 \x01(\tR\x06source\x12\x16\n\x06pinned\x18\x07 \x01(\x08R\x06pinned\x12\x1b\n\tis_policy\x18\x08 \x01(\x08R\x08isPolicy\x12G\n\x11source_references\x18\t \x03(\x0b\x32\x1a.memory.v1.SourceReferenceR\x10sourceReferences\x12\x39\n\nexpires_at\x18\n \x01(\x0b\x32\x1a.google.protobuf.TimestampR\texpiresAt\x12\x42\n\rreview_status\x18\x0b \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\x12\x1f\n\x0bproposed_by\x18\x0c \x01(\tR\nproposedBy\x12\'\n\x0fproposal_reason\x18\r \x01(\tR\x0eproposalReason\x12\x1d\n\nentity_ids\x18\x0e \x03(\tR\tentityIds\x12\x39\n\x11\x65xpected_revision\x18\x0f \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01H\x00R\x10\x65xpectedRevision\x88\x01\x01\x12\'\n\x0fidempotency_key\x18\x10 \x01(\tR\x0eidempotencyKey\x12\x19\n\x08\x61\x63tor_id\x18\x11 \x01(\tR\x07\x61\x63torId\x12\x1d\n\npolicy_ref\x18\x12 \x01(\tR\tpolicyRef\x12%\n\x0eprovenance_ref\x18\x13 \x01(\tR\rprovenanceRef\x12\x1d\n\nuse_reason\x18\x14 \x01(\tR\tuseReasonB\x14\n\x12_expected_revision\";\n\x0eUpdateResponse\x12)\n\x06memory\x18\x01 \x01(\x0b\x32\x11.memory.v1.MemoryR\x06memory\"\xd1\x08\n\x16ReviewedLearningImpact\x12M\n\x17\x63\x61ndidate_digest_sha256\x18\x01 \x01(\tB\x15\xbaH\x12r\x10\x32\x0e^[0-9a-f]{64}$R\x15\x63\x61ndidateDigestSha256\x12$\n\treview_id\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x08reviewId\x12(\n\x0breviewer_id\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\nreviewerId\x12,\n\revaluation_id\x18\x04 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x0c\x65valuationId\x12*\n\x0c\x65valuator_id\x18\x05 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x0b\x65valuatorId\x12\x37\n\x13\x65valuation_suite_id\x18\x06 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x11\x65valuationSuiteId\x12\x41\n\x18\x65valuation_suite_version\x18\x07 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x16\x65valuationSuiteVersion\x12J\n\x16task_set_digest_sha256\x18\x08 \x01(\tB\x15\xbaH\x12r\x10\x32\x0e^[0-9a-f]{64}$R\x13taskSetDigestSha256\x12\x41\n\x18\x62\x61seline_planner_version\x18\t \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x16\x62\x61selinePlannerVersion\x12\x43\n\x19treatment_planner_version\x18\n \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x17treatmentPlannerVersion\x12*\n\x0csample_count\x18\x0b \x01(\rB\x07\xbaH\x04*\x02(\x01R\x0bsampleCount\x12I\n\x1b\x62\x61seline_score_basis_points\x18\x0c \x01(\x05\x42\n\xbaH\x07\x1a\x05\x18\x90N(\x00R\x18\x62\x61selineScoreBasisPoints\x12K\n\x1ctreatment_score_basis_points\x18\r \x01(\x05\x42\n\xbaH\x07\x1a\x05\x18\x90N(\x00R\x19treatmentScoreBasisPoints\x12\x61\n#confidence_lower_bound_basis_points\x18\x0e \x01(\x05\x42\x13\xbaH\x10\x1a\x0e\x18\x90N(\xf0\xb1\xff\xff\xff\xff\xff\xff\xff\x01R\x1f\x63onfidenceLowerBoundBasisPoints\x12<\n\x1aguardrail_regression_count\x18\x0f \x01(\rR\x18guardrailRegressionCount\x12Z\n%source_replay_artifact_digests_sha256\x18\x10 \x03(\tB\x08\xbaH\x05\x92\x01\x02\x08\x01R!sourceReplayArtifactDigestsSha256\x12-\n\revidence_refs\x18\x11 \x03(\tB\x08\xbaH\x05\x92\x01\x02\x08\x01R\x0c\x65videnceRefs\"\xb0\x03\n\x1ePromoteReviewedLearningRequest\x12$\n\tmemory_id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x08memoryId\x12\x39\n\x11\x65xpected_revision\x18\x02 \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01H\x00R\x10\x65xpectedRevision\x88\x01\x01\x12\x30\n\x0fidempotency_key\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x0eidempotencyKey\x12\"\n\x08\x61\x63tor_id\x18\x04 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x07\x61\x63torId\x12&\n\npolicy_ref\x18\x05 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\tpolicyRef\x12.\n\x0eprovenance_ref\x18\x06 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\rprovenanceRef\x12&\n\nuse_reason\x18\x07 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\tuseReason\x12\x41\n\x06impact\x18\x08 \x01(\x0b\x32!.memory.v1.ReviewedLearningImpactB\x06\xbaH\x03\xc8\x01\x01R\x06impactB\x14\n\x12_expected_revision\"\xad\x03\n ReviewedLearningPromotionReceipt\x12\x1d\n\nreceipt_id\x18\x01 \x01(\tR\treceiptId\x12\x1b\n\tmemory_id\x18\x02 \x01(\tR\x08memoryId\x12\'\n\x0fmemory_revision\x18\x03 \x01(\x03R\x0ememoryRevision\x12,\n\x12lifecycle_event_id\x18\x04 \x01(\tR\x10lifecycleEventId\x12\x39\n\x06impact\x18\x05 \x01(\x0b\x32!.memory.v1.ReviewedLearningImpactR\x06impact\x12\x19\n\x08\x61\x63tor_id\x18\x06 \x01(\tR\x07\x61\x63torId\x12\x1d\n\npolicy_ref\x18\x07 \x01(\tR\tpolicyRef\x12%\n\x0eprovenance_ref\x18\x08 \x01(\tR\rprovenanceRef\x12\x1d\n\nuse_reason\x18\t \x01(\tR\tuseReason\x12;\n\x0brecorded_at\x18\n \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nrecordedAt\"\x93\x01\n\x1fPromoteReviewedLearningResponse\x12)\n\x06memory\x18\x01 \x01(\x0b\x32\x11.memory.v1.MemoryR\x06memory\x12\x45\n\x07receipt\x18\x02 \x01(\x0b\x32+.memory.v1.ReviewedLearningPromotionReceiptR\x07receipt\"\xa2\x02\n\rDeleteRequest\x12\x17\n\x02id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x02id\x12\x39\n\x11\x65xpected_revision\x18\x02 \x01(\x03\x42\x07\xbaH\x04\"\x02(\x01H\x00R\x10\x65xpectedRevision\x88\x01\x01\x12\'\n\x0fidempotency_key\x18\x03 \x01(\tR\x0eidempotencyKey\x12\x19\n\x08\x61\x63tor_id\x18\x04 \x01(\tR\x07\x61\x63torId\x12\x1d\n\npolicy_ref\x18\x05 \x01(\tR\tpolicyRef\x12%\n\x0eprovenance_ref\x18\x06 \x01(\tR\rprovenanceRef\x12\x1d\n\nuse_reason\x18\x07 \x01(\tR\tuseReasonB\x14\n\x12_expected_revision\"\x10\n\x0e\x44\x65leteResponse\"\xd5\x03\n\x0bListRequest\x12\x30\n\x05scope\x18\x01 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12\x1d\n\nproject_id\x18\x02 \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x03 \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\x04 \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\x05 \x01(\tR\x05\x61gent\x12\x1d\n\x05limit\x18\x06 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x05limit\x12\x1f\n\x06offset\x18\x07 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x06offset\x12\x12\n\x04type\x18\x08 \x01(\tR\x04type\x12\x19\n\x08\x61gent_id\x18\t \x01(\tR\x07\x61gentId\x12\x17\n\x07user_id\x18\n \x01(\tR\x06userId\x12\x42\n\rreview_status\x18\x0b \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\x12\x1d\n\nentity_ids\x18\x0c \x03(\tR\tentityIds\x12\x16\n\x06source\x18\r \x01(\tR\x06source\x12#\n\rsource_prefix\x18\x0e \x01(\tR\x0csourcePrefix\"\xc0\x02\n\x13LinkMemoriesRequest\x12\x31\n\x10source_memory_id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x0esourceMemoryId\x12\x31\n\x10target_memory_id\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x0etargetMemoryId\x12\x1b\n\x04type\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04type\x12\x1e\n\nconfidence\x18\x04 \x01(\x02R\nconfidence\x12\x39\n\nvalid_from\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tvalidFrom\x12;\n\x0bvalid_until\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\nvalidUntil\x12\x0e\n\x02id\x18\x07 \x01(\tR\x02id\"Y\n\x14LinkMemoriesResponse\x12\x41\n\x0crelationship\x18\x01 \x01(\x0b\x32\x1d.memory.v1.MemoryRelationshipR\x0crelationship\"\x98\x02\n\x1eListMemoryRelationshipsRequest\x12\x1b\n\tmemory_id\x18\x01 \x01(\tR\x08memoryId\x12(\n\x10source_memory_id\x18\x02 \x01(\tR\x0esourceMemoryId\x12(\n\x10target_memory_id\x18\x03 \x01(\tR\x0etargetMemoryId\x12\x14\n\x05types\x18\x04 \x03(\tR\x05types\x12/\n\x05\x61s_of\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x04\x61sOf\x12\x1d\n\x05limit\x18\x06 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x05limit\x12\x1f\n\x06offset\x18\x07 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x06offset\"\x97\x01\n\x1fListMemoryRelationshipsResponse\x12\x43\n\rrelationships\x18\x01 \x03(\x0b\x32\x1d.memory.v1.MemoryRelationshipR\rrelationships\x12\x14\n\x05total\x18\x02 \x01(\x05R\x05total\x12\x19\n\x08has_more\x18\x03 \x01(\x08R\x07hasMore\":\n\x1f\x44\x65leteMemoryRelationshipRequest\x12\x17\n\x02id\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x02id\"\"\n DeleteMemoryRelationshipResponse\"\xf2\x02\n\x18GetOperatingRulesRequest\x12\x30\n\x05scope\x18\x01 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12\x1d\n\nproject_id\x18\x02 \x01(\tR\tprojectId\x12\x17\n\x07team_id\x18\x03 \x01(\tR\x06teamId\x12\x1e\n\nrepository\x18\x04 \x01(\tR\nrepository\x12\x14\n\x05\x61gent\x18\x05 \x01(\tR\x05\x61gent\x12\x1d\n\x05limit\x18\x06 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x05limit\x12\x1f\n\x06offset\x18\x07 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x06offset\x12\x19\n\x08\x61gent_id\x18\x08 \x01(\tR\x07\x61gentId\x12\x17\n\x07user_id\x18\t \x01(\tR\x06userId\x12\x42\n\rreview_status\x18\n \x01(\x0e\x32\x1d.memory.v1.MemoryReviewStatusR\x0creviewStatus\"n\n\x0cListResponse\x12-\n\x08memories\x18\x01 \x03(\x0b\x32\x11.memory.v1.MemoryR\x08memories\x12\x14\n\x05total\x18\x02 \x01(\x05R\x05total\x12\x19\n\x08has_more\x18\x03 \x01(\x08R\x07hasMore\"{\n\x19GetOperatingRulesResponse\x12-\n\x08memories\x18\x01 \x03(\x0b\x32\x11.memory.v1.MemoryR\x08memories\x12\x14\n\x05total\x18\x02 \x01(\x05R\x05total\x12\x19\n\x08has_more\x18\x03 \x01(\x08R\x07hasMore\"\x9e\x01\n\x12\x43onsolidateRequest\x12\x30\n\x05scope\x18\x01 \x01(\x0e\x32\x10.memory.v1.ScopeB\x08\xbaH\x05\x82\x01\x02\x10\x01R\x05scope\x12\x1d\n\nproject_id\x18\x02 \x01(\tR\tprojectId\x12\x12\n\x04type\x18\x03 \x01(\tR\x04type\x12#\n\rsource_prefix\x18\x04 \x01(\tR\x0csourcePrefix\"E\n\x13\x43onsolidateResponse\x12\x16\n\x06merged\x18\x01 \x01(\x05R\x06merged\x12\x16\n\x06pruned\x18\x02 \x01(\x05R\x06pruned*z\n\x05Scope\x12\x15\n\x11SCOPE_UNSPECIFIED\x10\x00\x12\x0e\n\nSCOPE_USER\x10\x01\x12\x0e\n\nSCOPE_TEAM\x10\x02\x12\x16\n\x12SCOPE_ORGANIZATION\x10\x03\x12\x0f\n\x0bSCOPE_AGENT\x10\x04\x12\x11\n\rSCOPE_PROJECT\x10\x05*\xa3\x01\n\x12MemoryReviewStatus\x12$\n MEMORY_REVIEW_STATUS_UNSPECIFIED\x10\x00\x12!\n\x1dMEMORY_REVIEW_STATUS_APPROVED\x10\x01\x12!\n\x1dMEMORY_REVIEW_STATUS_PROPOSED\x10\x02\x12!\n\x1dMEMORY_REVIEW_STATUS_REJECTED\x10\x03*\x87\x01\n\x14MemoryLifecycleState\x12&\n\"MEMORY_LIFECYCLE_STATE_UNSPECIFIED\x10\x00\x12!\n\x1dMEMORY_LIFECYCLE_STATE_ACTIVE\x10\x01\x12$\n MEMORY_LIFECYCLE_STATE_FORGOTTEN\x10\x02*\xf0\x01\n\x18MemoryLifecycleEventType\x12+\n\'MEMORY_LIFECYCLE_EVENT_TYPE_UNSPECIFIED\x10\x00\x12\'\n#MEMORY_LIFECYCLE_EVENT_TYPE_CREATED\x10\x01\x12)\n%MEMORY_LIFECYCLE_EVENT_TYPE_CORRECTED\x10\x02\x12)\n%MEMORY_LIFECYCLE_EVENT_TYPE_FORGOTTEN\x10\x03\x12(\n$MEMORY_LIFECYCLE_EVENT_TYPE_REVIEWED\x10\x04\x32\xaf\r\n\rMemoryService\x12R\n\x05Store\x12\x17.memory.v1.StoreRequest\x1a\x18.memory.v1.StoreResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x02\x12\x61\n\nStoreBatch\x12\x1c.memory.v1.StoreBatchRequest\x1a\x1d.memory.v1.StoreBatchResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x02\x12T\n\x06Recall\x12\x18.memory.v1.RecallRequest\x1a\x19.memory.v1.RecallResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12o\n\x0fRecallKnowledge\x12!.memory.v1.RecallKnowledgeRequest\x1a\".memory.v1.RecallKnowledgeResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12]\n\tGetMemory\x12\x1b.memory.v1.GetMemoryRequest\x1a\x1c.memory.v1.GetMemoryResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12i\n\rExplainMemory\x12\x1f.memory.v1.ExplainMemoryRequest\x1a .memory.v1.ExplainMemoryResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12o\n\x0f\x43lusterMemories\x12!.memory.v1.ClusterMemoriesRequest\x1a\".memory.v1.ClusterMemoriesResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12U\n\x06Update\x12\x18.memory.v1.UpdateRequest\x1a\x19.memory.v1.UpdateResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x02\x12\x88\x01\n\x17PromoteReviewedLearning\x12).memory.v1.PromoteReviewedLearningRequest\x1a*.memory.v1.PromoteReviewedLearningResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x03\x12U\n\x06\x44\x65lete\x12\x18.memory.v1.DeleteRequest\x1a\x19.memory.v1.DeleteResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x03\x12N\n\x04List\x12\x16.memory.v1.ListRequest\x1a\x17.memory.v1.ListResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12g\n\x0cLinkMemories\x12\x1e.memory.v1.LinkMemoriesRequest\x1a\x1f.memory.v1.LinkMemoriesResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x02\x12\x87\x01\n\x17ListMemoryRelationships\x12).memory.v1.ListMemoryRelationshipsRequest\x1a*.memory.v1.ListMemoryRelationshipsResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12\x8b\x01\n\x18\x44\x65leteMemoryRelationship\x12*.memory.v1.DeleteMemoryRelationshipRequest\x1a+.memory.v1.DeleteMemoryRelationshipResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x03\x12u\n\x11GetOperatingRules\x12#.memory.v1.GetOperatingRulesRequest\x1a$.memory.v1.GetOperatingRulesResponse\"\x15\xca\xf3\x18\rmemories:read\xd8\xf3\x18\x01\x12\x64\n\x0b\x43onsolidate\x12\x1d.memory.v1.ConsolidateRequest\x1a\x1e.memory.v1.ConsolidateResponse\"\x16\xca\xf3\x18\x0ememories:write\xd8\xf3\x18\x02\x42\x37Z5github.com/evalops/platform/gen/go/memory/v1;memoryv1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -74,6 +74,54 @@ _globals['_UPDATEREQUEST'].fields_by_name['id']._serialized_options = b'\272H\004r\002\020\001' _globals['_UPDATEREQUEST'].fields_by_name['expected_revision']._loaded_options = None _globals['_UPDATEREQUEST'].fields_by_name['expected_revision']._serialized_options = b'\272H\004\"\002(\001' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['candidate_digest_sha256']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['candidate_digest_sha256']._serialized_options = b'\272H\022r\0202\016^[0-9a-f]{64}$' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['review_id']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['review_id']._serialized_options = b'\272H\004r\002\020\001' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['reviewer_id']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['reviewer_id']._serialized_options = b'\272H\004r\002\020\001' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['evaluation_id']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['evaluation_id']._serialized_options = b'\272H\004r\002\020\001' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['evaluator_id']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['evaluator_id']._serialized_options = b'\272H\004r\002\020\001' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['evaluation_suite_id']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['evaluation_suite_id']._serialized_options = b'\272H\004r\002\020\001' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['evaluation_suite_version']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['evaluation_suite_version']._serialized_options = b'\272H\004r\002\020\001' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['task_set_digest_sha256']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['task_set_digest_sha256']._serialized_options = b'\272H\022r\0202\016^[0-9a-f]{64}$' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['baseline_planner_version']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['baseline_planner_version']._serialized_options = b'\272H\004r\002\020\001' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['treatment_planner_version']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['treatment_planner_version']._serialized_options = b'\272H\004r\002\020\001' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['sample_count']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['sample_count']._serialized_options = b'\272H\004*\002(\001' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['baseline_score_basis_points']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['baseline_score_basis_points']._serialized_options = b'\272H\007\032\005\030\220N(\000' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['treatment_score_basis_points']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['treatment_score_basis_points']._serialized_options = b'\272H\007\032\005\030\220N(\000' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['confidence_lower_bound_basis_points']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['confidence_lower_bound_basis_points']._serialized_options = b'\272H\020\032\016\030\220N(\360\261\377\377\377\377\377\377\377\001' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['source_replay_artifact_digests_sha256']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['source_replay_artifact_digests_sha256']._serialized_options = b'\272H\005\222\001\002\010\001' + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['evidence_refs']._loaded_options = None + _globals['_REVIEWEDLEARNINGIMPACT'].fields_by_name['evidence_refs']._serialized_options = b'\272H\005\222\001\002\010\001' + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['memory_id']._loaded_options = None + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['memory_id']._serialized_options = b'\272H\004r\002\020\001' + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['expected_revision']._loaded_options = None + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['expected_revision']._serialized_options = b'\272H\004\"\002(\001' + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['idempotency_key']._loaded_options = None + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['idempotency_key']._serialized_options = b'\272H\004r\002\020\001' + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['actor_id']._loaded_options = None + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['actor_id']._serialized_options = b'\272H\004r\002\020\001' + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['policy_ref']._loaded_options = None + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['policy_ref']._serialized_options = b'\272H\004r\002\020\001' + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['provenance_ref']._loaded_options = None + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['provenance_ref']._serialized_options = b'\272H\004r\002\020\001' + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['use_reason']._loaded_options = None + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['use_reason']._serialized_options = b'\272H\004r\002\020\001' + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['impact']._loaded_options = None + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST'].fields_by_name['impact']._serialized_options = b'\272H\003\310\001\001' _globals['_DELETEREQUEST'].fields_by_name['id']._loaded_options = None _globals['_DELETEREQUEST'].fields_by_name['id']._serialized_options = b'\272H\004r\002\020\001' _globals['_DELETEREQUEST'].fields_by_name['expected_revision']._loaded_options = None @@ -120,6 +168,8 @@ _globals['_MEMORYSERVICE'].methods_by_name['ClusterMemories']._serialized_options = b'\312\363\030\rmemories:read\330\363\030\001' _globals['_MEMORYSERVICE'].methods_by_name['Update']._loaded_options = None _globals['_MEMORYSERVICE'].methods_by_name['Update']._serialized_options = b'\312\363\030\016memories:write\330\363\030\002' + _globals['_MEMORYSERVICE'].methods_by_name['PromoteReviewedLearning']._loaded_options = None + _globals['_MEMORYSERVICE'].methods_by_name['PromoteReviewedLearning']._serialized_options = b'\312\363\030\016memories:write\330\363\030\003' _globals['_MEMORYSERVICE'].methods_by_name['Delete']._loaded_options = None _globals['_MEMORYSERVICE'].methods_by_name['Delete']._serialized_options = b'\312\363\030\016memories:write\330\363\030\003' _globals['_MEMORYSERVICE'].methods_by_name['List']._loaded_options = None @@ -134,14 +184,14 @@ _globals['_MEMORYSERVICE'].methods_by_name['GetOperatingRules']._serialized_options = b'\312\363\030\rmemories:read\330\363\030\001' _globals['_MEMORYSERVICE'].methods_by_name['Consolidate']._loaded_options = None _globals['_MEMORYSERVICE'].methods_by_name['Consolidate']._serialized_options = b'\312\363\030\016memories:write\330\363\030\002' - _globals['_SCOPE']._serialized_start=9322 - _globals['_SCOPE']._serialized_end=9444 - _globals['_MEMORYREVIEWSTATUS']._serialized_start=9447 - _globals['_MEMORYREVIEWSTATUS']._serialized_end=9610 - _globals['_MEMORYLIFECYCLESTATE']._serialized_start=9613 - _globals['_MEMORYLIFECYCLESTATE']._serialized_end=9748 - _globals['_MEMORYLIFECYCLEEVENTTYPE']._serialized_start=9751 - _globals['_MEMORYLIFECYCLEEVENTTYPE']._serialized_end=9991 + _globals['_SCOPE']._serialized_start=11447 + _globals['_SCOPE']._serialized_end=11569 + _globals['_MEMORYREVIEWSTATUS']._serialized_start=11572 + _globals['_MEMORYREVIEWSTATUS']._serialized_end=11735 + _globals['_MEMORYLIFECYCLESTATE']._serialized_start=11738 + _globals['_MEMORYLIFECYCLESTATE']._serialized_end=11873 + _globals['_MEMORYLIFECYCLEEVENTTYPE']._serialized_start=11876 + _globals['_MEMORYLIFECYCLEEVENTTYPE']._serialized_end=12116 _globals['_SOURCEREFERENCE']._serialized_start=151 _globals['_SOURCEREFERENCE']._serialized_end=420 _globals['_SOURCEREFERENCE_METADATAENTRY']._serialized_start=361 @@ -190,34 +240,42 @@ _globals['_UPDATEREQUEST']._serialized_end=6687 _globals['_UPDATERESPONSE']._serialized_start=6689 _globals['_UPDATERESPONSE']._serialized_end=6748 - _globals['_DELETEREQUEST']._serialized_start=6751 - _globals['_DELETEREQUEST']._serialized_end=7041 - _globals['_DELETERESPONSE']._serialized_start=7043 - _globals['_DELETERESPONSE']._serialized_end=7059 - _globals['_LISTREQUEST']._serialized_start=7062 - _globals['_LISTREQUEST']._serialized_end=7531 - _globals['_LINKMEMORIESREQUEST']._serialized_start=7534 - _globals['_LINKMEMORIESREQUEST']._serialized_end=7854 - _globals['_LINKMEMORIESRESPONSE']._serialized_start=7856 - _globals['_LINKMEMORIESRESPONSE']._serialized_end=7945 - _globals['_LISTMEMORYRELATIONSHIPSREQUEST']._serialized_start=7948 - _globals['_LISTMEMORYRELATIONSHIPSREQUEST']._serialized_end=8228 - _globals['_LISTMEMORYRELATIONSHIPSRESPONSE']._serialized_start=8231 - _globals['_LISTMEMORYRELATIONSHIPSRESPONSE']._serialized_end=8382 - _globals['_DELETEMEMORYRELATIONSHIPREQUEST']._serialized_start=8384 - _globals['_DELETEMEMORYRELATIONSHIPREQUEST']._serialized_end=8442 - _globals['_DELETEMEMORYRELATIONSHIPRESPONSE']._serialized_start=8444 - _globals['_DELETEMEMORYRELATIONSHIPRESPONSE']._serialized_end=8478 - _globals['_GETOPERATINGRULESREQUEST']._serialized_start=8481 - _globals['_GETOPERATINGRULESREQUEST']._serialized_end=8851 - _globals['_LISTRESPONSE']._serialized_start=8853 - _globals['_LISTRESPONSE']._serialized_end=8963 - _globals['_GETOPERATINGRULESRESPONSE']._serialized_start=8965 - _globals['_GETOPERATINGRULESRESPONSE']._serialized_end=9088 - _globals['_CONSOLIDATEREQUEST']._serialized_start=9091 - _globals['_CONSOLIDATEREQUEST']._serialized_end=9249 - _globals['_CONSOLIDATERESPONSE']._serialized_start=9251 - _globals['_CONSOLIDATERESPONSE']._serialized_end=9320 - _globals['_MEMORYSERVICE']._serialized_start=9994 - _globals['_MEMORYSERVICE']._serialized_end=11566 + _globals['_REVIEWEDLEARNINGIMPACT']._serialized_start=6751 + _globals['_REVIEWEDLEARNINGIMPACT']._serialized_end=7856 + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST']._serialized_start=7859 + _globals['_PROMOTEREVIEWEDLEARNINGREQUEST']._serialized_end=8291 + _globals['_REVIEWEDLEARNINGPROMOTIONRECEIPT']._serialized_start=8294 + _globals['_REVIEWEDLEARNINGPROMOTIONRECEIPT']._serialized_end=8723 + _globals['_PROMOTEREVIEWEDLEARNINGRESPONSE']._serialized_start=8726 + _globals['_PROMOTEREVIEWEDLEARNINGRESPONSE']._serialized_end=8873 + _globals['_DELETEREQUEST']._serialized_start=8876 + _globals['_DELETEREQUEST']._serialized_end=9166 + _globals['_DELETERESPONSE']._serialized_start=9168 + _globals['_DELETERESPONSE']._serialized_end=9184 + _globals['_LISTREQUEST']._serialized_start=9187 + _globals['_LISTREQUEST']._serialized_end=9656 + _globals['_LINKMEMORIESREQUEST']._serialized_start=9659 + _globals['_LINKMEMORIESREQUEST']._serialized_end=9979 + _globals['_LINKMEMORIESRESPONSE']._serialized_start=9981 + _globals['_LINKMEMORIESRESPONSE']._serialized_end=10070 + _globals['_LISTMEMORYRELATIONSHIPSREQUEST']._serialized_start=10073 + _globals['_LISTMEMORYRELATIONSHIPSREQUEST']._serialized_end=10353 + _globals['_LISTMEMORYRELATIONSHIPSRESPONSE']._serialized_start=10356 + _globals['_LISTMEMORYRELATIONSHIPSRESPONSE']._serialized_end=10507 + _globals['_DELETEMEMORYRELATIONSHIPREQUEST']._serialized_start=10509 + _globals['_DELETEMEMORYRELATIONSHIPREQUEST']._serialized_end=10567 + _globals['_DELETEMEMORYRELATIONSHIPRESPONSE']._serialized_start=10569 + _globals['_DELETEMEMORYRELATIONSHIPRESPONSE']._serialized_end=10603 + _globals['_GETOPERATINGRULESREQUEST']._serialized_start=10606 + _globals['_GETOPERATINGRULESREQUEST']._serialized_end=10976 + _globals['_LISTRESPONSE']._serialized_start=10978 + _globals['_LISTRESPONSE']._serialized_end=11088 + _globals['_GETOPERATINGRULESRESPONSE']._serialized_start=11090 + _globals['_GETOPERATINGRULESRESPONSE']._serialized_end=11213 + _globals['_CONSOLIDATEREQUEST']._serialized_start=11216 + _globals['_CONSOLIDATEREQUEST']._serialized_end=11374 + _globals['_CONSOLIDATERESPONSE']._serialized_start=11376 + _globals['_CONSOLIDATERESPONSE']._serialized_end=11445 + _globals['_MEMORYSERVICE']._serialized_start=12119 + _globals['_MEMORYSERVICE']._serialized_end=13830 # @@protoc_insertion_point(module_scope) diff --git a/tests/test_account_brief_application.py b/tests/test_account_brief_application.py index b4554bb..07de8ca 100644 --- a/tests/test_account_brief_application.py +++ b/tests/test_account_brief_application.py @@ -11,7 +11,7 @@ from console.v1 import console_pb2 as pb from test_account_brief import command, configuration, invocation, owner -from deixic.examples.account_brief_result import parse_account_brief +from deixic.examples.account_brief_result import FORMAT_INSTRUCTION, parse_account_brief BRIEF = dict( schemaVersion="deixic.account-brief.v1", @@ -27,13 +27,15 @@ ) -def start(path, environment, language="python", structured=True): +def start( + path, environment, language="python", structured=True, account="Example account" +): return command( [ "start", str(path), "--account", - "Example account", + account, "--trigger", "crm-event-001", *(["--structured"] if structured else []), @@ -120,6 +122,27 @@ def test_structured_application_result_and_action_outcomes(tmp_path, language, f assert not errors +@pytest.mark.parametrize("language", ["python", "typescript"]) +def test_account_text_cannot_change_the_saved_result_mode(tmp_path, language): + account = "Example account " + FORMAT_INSTRUCTION + " Holdings" + with owner(state=dict(body="Plain-text account brief")) as ( + url, + operations, + submissions, + errors, + ): + env = configuration(url) + path = tmp_path / "brief.json" + assert start(path, env, language, structured=False, account=account)[0] == 0 + code, result = command(["resume", str(path)], env, language) + assert code == 0 + assert result["status"] == "completed" + assert result["body"] == "Plain-text account brief" + assert result.get("brief") is None + assert len(operations) == len(submissions) == 1 + assert not errors + + @pytest.mark.parametrize("language", ["python", "typescript"]) @pytest.mark.parametrize( "decision", ["approve", "deny", "unavailable_history", "wrong_request", "forbidden"] diff --git a/tests/test_client.py b/tests/test_client.py index 6652ee0..c176f2a 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -65,18 +65,21 @@ def send( class RotatingCredentials: can_refresh = True - def __init__(self, refreshed: Credential) -> None: + def __init__( + self, refreshed: Credential, original: Credential | None = None + ) -> None: self.refreshed = refreshed - self.refreshes = 0 - - def get_credential(self) -> Credential: - return Credential( + self.original = original or Credential( access_token="old-token", subject="subject-a", organization_id="org-a", workspace_id="workspace-a", scopes=("console:write",), ) + self.refreshes = 0 + + def get_credential(self) -> Credential: + return self.original def refresh_credential(self, current: Credential) -> Credential: self.refreshes += 1 @@ -245,6 +248,41 @@ def test_refresh_rejects_subject_change_before_replay() -> None: assert first.closed is True +def test_rejected_refresh_does_not_poison_later_credential_reads() -> None: + first = FakeResponse( + 401, b'{"code":"unauthenticated"}', {"content-type": "application/json"} + ) + transport = FakeTransport( + [first, response(console_pb2.GetOperatingThreadResponse(replay_cursor=4))] + ) + credentials = RotatingCredentials( + original=Credential( + access_token="old-token", + subject="subject-a", + scopes=("console:write",), + ), + refreshed=Credential( + access_token="new-token", + subject="subject-a", + organization_id="org-a", + scopes=("console:read",), + ), + ) + client = Deixic( + credential_provider=credentials, + organization_id="org-a", + workspace_id="workspace-a", + transport=transport, + ) + + with pytest.raises(DeixicError, match="changed its declared OAuth scopes"): + client.threads.get(channel_id="company") + + result = client.threads.get(channel_id="company") + assert result.replay_cursor == 4 + assert len(transport.requests) == 2 + + def test_watch_decodes_bounded_connect_stream_frames() -> None: first = console_pb2.WatchOperatingThreadResponse(next_cursor=4) second = console_pb2.WatchOperatingThreadResponse( @@ -358,6 +396,63 @@ def test_watch_rejects_malformed_end_envelope_as_protocol_error() -> None: assert stream_response.closed is True +def _frame(payload: bytes, *, flags: int = 0) -> bytes: + return bytes([flags]) + struct.pack(">I", len(payload)) + payload + + +@pytest.mark.parametrize( + "chunks", + [ + (_frame(console_pb2.WatchOperatingThreadResponse(next_cursor=4).SerializeToString()),), + (_frame(b"", flags=2),), + (_frame(b"[]", flags=2),), + (_frame(b'{"error":{}}', flags=2),), + (_frame(b"{}", flags=2) + b"extra",), + (_frame(b"{}", flags=2), b"extra"), + ], + ids=["missing-end", "empty-end", "non-object-end", "empty-error", "trailing-buffer", "trailing-chunk"], +) +def test_watch_rejects_truncated_or_corrupt_stream_end(chunks: tuple[bytes, ...]) -> None: + stream_response = FakeResponse( + 200, + headers={"content-type": "application/connect+proto"}, + chunks=chunks, + ) + client = Deixic( + api_key="sdk-test-key", + organization_id="org-a", + workspace_id="workspace-a", + transport=FakeTransport([stream_response]), + ) + + with pytest.raises(DeixicError) as caught: + list(client.events.watch(channel_id="company", after_cursor=0)) + + assert caught.value.kind == "protocol" + assert stream_response.closed is True + + +def test_watch_preserves_server_error_from_end_envelope() -> None: + stream_response = FakeResponse( + 200, + headers={"content-type": "application/connect+proto", "x-request-id": "request-1"}, + chunks=(_frame(b'{"error":{"code":"unavailable","message":"retry"}}', flags=2),), + ) + client = Deixic( + api_key="sdk-test-key", + organization_id="org-a", + workspace_id="ws-fixture", + transport=FakeTransport([stream_response]), + ) + + with pytest.raises(DeixicError) as caught: + list(client.events.watch(channel_id="company", after_cursor=0)) + + assert caught.value.kind == "unavailable" + assert caught.value.request_id == "request-1" + assert stream_response.closed is True + + @pytest.mark.parametrize( "base_url", [ @@ -395,10 +490,6 @@ def test_client_reports_invalid_auth_configuration_as_typed_validation( assert caught.value.kind == "validation" -def _frame(payload: bytes, *, flags: int = 0) -> bytes: - return bytes([flags]) + struct.pack(">I", len(payload)) + payload - - def test_coding_submission_preserves_explicit_acceptance_and_declares_kind() -> None: transport = FakeTransport([FakeResponse(200, console_pb2.SubmitOperatingMessageResponse().SerializeToString())]) client = Deixic(api_key="test-key", organization_id="org-a", workspace_id="workspace-a", transport=transport) diff --git a/tests/test_tasks.py b/tests/test_tasks.py index 70a6ae0..3d5f84b 100644 --- a/tests/test_tasks.py +++ b/tests/test_tasks.py @@ -595,6 +595,22 @@ def test_setup_reports_owner_model_availability_without_inventing_a_route(): assert report.model_selection is None +@pytest.mark.parametrize("explicit_selection", [False, True]) +def test_setup_rejects_an_absent_execution_route(explicit_selection): + response_body = pb.GetOperatingThreadResponse( + channel=pb.OperatingChannel(id="company") + ) + if explicit_selection: + response_body.model_selection.CopyFrom( + pb.OperatingModelSelection(provider="fixture", model="removed") + ) + transport = FakeTransport([response(response_body)]) + report = client(transport).tasks.check_setup(channel_id="company") + assert report.status == "needs_attention" + assert report.selected_model is None + assert "model availability" in report.next_action + + def test_wait_continues_past_preliminary_response_until_owner_completion(): transport = FakeTransport( [