diff --git a/.repository-projection.json b/.repository-projection.json index b4e607f..f9f551b 100644 --- a/.repository-projection.json +++ b/.repository-projection.json @@ -3,11 +3,11 @@ "projection": "deixic-python", "projectionSchemaVersion": 1, "sourceRepository": "dx-corp/mono", - "sourceSha": "ec9e1d787745e301ecb871186224dc34f6707147", + "sourceSha": "21f8bdad3c2009ea769db44ebdd743a09f7e1f45", "destinationRepository": "dx-corp/deixic-python", - "priorProjectedBase": "f85ce38b4c7535b7c800af03996ecfea1c50894e", + "priorProjectedBase": "b696ff3e2db09dfadc8076258f5c2646292404a6", "definitionDigest": "eedaf99642ef977b56b6e12ce151e1834670560f00294e89224f0628882937d9", "toolDigest": "535e3cb77f0b59898e63a5f097fb3308564bafbc", - "contentDigest": "496279dc412b804f4aaa40f7b04f4c88f1a43990e2edbe5f9885f603b317d51d", + "contentDigest": "f381dd1578d25581206ff0c88037bd5adfe8bb981b529f93a59491b03e060584", "publicationEligible": true } diff --git a/README.md b/README.md index 1d5b87c..983924a 100644 --- a/README.md +++ b/README.md @@ -357,3 +357,28 @@ IDs and decimal-string cursors. Their `channelId` identifies the public thread. Python message types are available from `deixic.protocol`; TypeScript exports public message types and schemas from the package root. Existing TypeScript operating-type names are aliases of these public types. + + +## Brand voices + +`voices.list()` reads active voice IDs and display metadata for this client's fixed workspace. +Guidance remains with the Settings owner. Select up to four IDs in order; the first leads. +Explicit selections use `SubmitVoicedTask`, which older servers refuse before acceptance. +Ordinary submissions continue to use `SubmitTask` and the workspace default. + +Tasks prepared with an explicit selection use the shared `deixic.task.v2` checkpoint. +It retains the IDs and tone adjustments across restart and explicit replay with the same +idempotency key. Existing `deixic.task.v1` checkpoints retain their original request. +Do not change an uncertain request's selection; start a separate logical request instead. + +```python +from deixic import protocol as pb +catalog = deixic.voices.list() +task = deixic.tasks.prepare( + channel_id="company", body="Draft the update", idempotency_key="update-1", + voice_selection=pb.VoiceSelection(mode=pb.VOICE_MODE_BRAND_VOICE, + voice_ids=["brand", "customer-care"], tone_adjustments=[pb.VOICE_TONE_WARMER]), + on_checkpoint=save_checkpoint, +) +task.submit() +``` diff --git a/src/deixic/client.py b/src/deixic/client.py index a5b8be3..d6c4be1 100644 --- a/src/deixic/client.py +++ b/src/deixic/client.py @@ -68,6 +68,7 @@ def __init__( self.threads = ThreadsClient(self) self.events = EventsClient(self) self.messages = MessagesClient(self) + self.voices = VoicesClient(self) self.controls = ControlsClient(self) self.receipts = ReceiptsClient(self) from .tasks import TasksClient @@ -279,6 +280,7 @@ def send( reference_task_ids: tuple[str, ...] | list[str] = (), project_resource_id: str | None = None, coding_acceptance: public_pb2.CodingContract | None = None, + voice_selection: public_pb2.VoiceSelection | None = None, ) -> public_pb2.SubmitTaskResponse: request = public_pb2.SubmitTaskRequest( scope=self._client._scope(), @@ -294,6 +296,17 @@ def send( request.project_resource_id = _required( project_resource_id, "project_resource_id" ) + if voice_selection is not None: + # Snapshot before credential callbacks; a 401 replays identical bytes. + selection = normalize_voice_selection(voice_selection) + result = self._client._unary( + "SubmitVoicedTask", + public_pb2.SubmitVoicedTaskRequest(task=request, voice_selection=selection), + public_pb2.SubmitVoicedTaskResponse, + ) + if not result.HasField("result"): + raise DeixicError("Voiced submission omitted its result", kind="protocol") + return result.result return self._client._unary( "SubmitTask", request, @@ -523,3 +536,29 @@ def _bounded_int(value: int, field: str, *, minimum: int, maximum: int) -> None: raise validation_error( f"{field} must be an integer between {minimum} and {maximum}" ) + + +class VoicesClient: + def __init__(self, client: Deixic) -> None: + self._client = client + + def list(self) -> public_pb2.GetVoiceCatalogResponse: + result = self._client._unary( + "GetVoiceCatalog", public_pb2.GetVoiceCatalogRequest(scope=self._client._scope()), + public_pb2.GetVoiceCatalogResponse, + ) + if result.scope != self._client._scope(): + raise DeixicError("Voice catalog belongs to a different workspace", kind="protocol") + return result + + +def normalize_voice_selection(value: public_pb2.VoiceSelection) -> public_pb2.VoiceSelection: + if not isinstance(value, public_pb2.VoiceSelection): + raise validation_error("Invalid voice selection") + ids, tones = list(value.voice_ids), list(value.tone_adjustments) + if (value.mode not in (0, 1, 2, 3) or len(ids) > 4 or len(ids) != len(set(ids)) + or any(not item or item != item.strip() or len(item) > 128 for item in ids) + or (not ids if value.mode == 2 else bool(ids)) + or len(tones) > 3 or any(tone not in (1, 2, 3) for tone in tones)): + raise validation_error("Invalid voice IDs or tone adjustments") + return public_pb2.VoiceSelection(mode=value.mode, voice_ids=ids, tone_adjustments=sorted(set(tones))) diff --git a/src/deixic/tasks.py b/src/deixic/tasks.py index 4fbb8a3..267e23b 100644 --- a/src/deixic/tasks.py +++ b/src/deixic/tasks.py @@ -2,6 +2,7 @@ from __future__ import annotations +from copy import deepcopy import math import random import time @@ -22,8 +23,8 @@ MAX_CURSOR = 2**63 - 1 -class TaskCheckpoint(TypedDict): - schema: Literal["deixic.task.v1"] +class _TaskCheckpointBase(TypedDict): + schema: Literal["deixic.task.v1", "deixic.task.v2"] organizationId: str workspaceId: str baseUrl: str @@ -37,6 +38,10 @@ class TaskCheckpoint(TypedDict): cursor: str +class TaskCheckpoint(_TaskCheckpointBase, total=False): + voiceSelection: dict[str, Any] + + @dataclass(frozen=True) class TaskResult: status: Literal[ @@ -90,6 +95,7 @@ def prepare( body: str, idempotency_key: str, project_resource_id: str = "", + voice_selection: pb.VoiceSelection | None = None, on_checkpoint: Callable[[TaskCheckpoint], None] | None = None, ) -> Task: state: TaskCheckpoint = dict( @@ -108,6 +114,9 @@ def prepare( sequence="0", cursor="0", ) + if voice_selection is not None: + state["schema"] = "deixic.task.v2" + state["voiceSelection"] = _voice_checkpoint(voice_selection) task = Task(self._client, state, on_checkpoint) task._save() return task @@ -119,6 +128,7 @@ def start( body: str, idempotency_key: str, project_resource_id: str = "", + voice_selection: pb.VoiceSelection | None = None, on_checkpoint: Callable[[TaskCheckpoint], None] | None = None, ) -> Task: """Prepare and submit once. Use on_checkpoint for restart recovery.""" @@ -127,6 +137,7 @@ def start( body=body, idempotency_key=idempotency_key, project_resource_id=project_resource_id, + voice_selection=voice_selection, on_checkpoint=on_checkpoint, ).submit() @@ -137,12 +148,17 @@ def resume( on_checkpoint: Callable[[TaskCheckpoint], None] | None = None, ) -> Task: # A checkpoint supplies coordinates, never authorization or completion. - keys = TaskCheckpoint.__required_keys__ + keys = {"schema", "organizationId", "workspaceId", "baseUrl", "channelId", "body", + "idempotencyKey", "projectResourceId", "submission", "turnId", "sequence", "cursor"} + if isinstance(checkpoint, Mapping) and checkpoint.get("schema") == "deixic.task.v2": + keys.add("voiceSelection") if not isinstance(checkpoint, Mapping) or set(checkpoint) != keys: raise validation_error("Invalid task checkpoint fields") - state = dict(checkpoint) - if state["schema"] != "deixic.task.v1": + state = deepcopy(dict(checkpoint)) + if state["schema"] not in ("deixic.task.v1", "deixic.task.v2"): raise validation_error("Unsupported task checkpoint schema") + if state["schema"] == "deixic.task.v2": + state["voiceSelection"] = _voice_checkpoint(_voice_from_checkpoint(state["voiceSelection"])) if (state["organizationId"], state["workspaceId"], state["baseUrl"]) != ( self._client.organization_id, self._client.workspace_id, @@ -241,7 +257,7 @@ def __init__( if on_checkpoint is not None and not callable(on_checkpoint): raise validation_error("on_checkpoint must be callable") self._client = client - self._state = cast(TaskCheckpoint, dict(state)) + self._state = cast(TaskCheckpoint, deepcopy(state)) self._on_checkpoint = on_checkpoint self._event: pb.TaskEvent | None = None self._submitting = False @@ -249,7 +265,7 @@ def __init__( def checkpoint(self) -> TaskCheckpoint: """JSON-safe coordinates and original request; excludes credentials.""" - return cast(TaskCheckpoint, dict(self._state)) + return cast(TaskCheckpoint, deepcopy(self._state)) def _save(self) -> None: if self._on_checkpoint: @@ -276,6 +292,8 @@ def _submit(self, required: str) -> Task: body=self._state["body"], idempotency_key=self._state["idempotencyKey"], project_resource_id=self._state["projectResourceId"] or None, + **({"voice_selection": _voice_from_checkpoint(self._state["voiceSelection"])} + if self._state["schema"] == "deixic.task.v2" else {}), ) turn = accepted.accepted_turn if ( @@ -654,3 +672,26 @@ def _validate_page(page: pb.ListEventsResponse, cursor: int) -> None: if event.cursor in records and records[event.cursor] != encoded: raise _protocol("Different events reused the same cursor") records[event.cursor] = encoded + + +def _voice_checkpoint(value: pb.VoiceSelection) -> dict[str, Any]: + from .client import normalize_voice_selection + selected = normalize_voice_selection(value) + return {"mode": selected.mode, "voiceIds": list(selected.voice_ids), + "toneAdjustments": list(selected.tone_adjustments)} + + +def _voice_from_checkpoint(value: Any) -> pb.VoiceSelection: + if (not isinstance(value, dict) or set(value) != {"mode", "voiceIds", "toneAdjustments"} + or type(value["mode"]) is not int or not isinstance(value["voiceIds"], list) + or not isinstance(value["toneAdjustments"], list) + or len(value["voiceIds"]) > 4 or len(value["toneAdjustments"]) > 3 + or any(not isinstance(item, str) for item in value["voiceIds"]) + or any(type(item) is not int for item in value["toneAdjustments"])): + raise validation_error("Invalid checkpoint voice selection") + try: + from .client import normalize_voice_selection + return normalize_voice_selection(pb.VoiceSelection( + mode=value["mode"], voice_ids=value["voiceIds"], tone_adjustments=value["toneAdjustments"])) + except (TypeError, ValueError, OverflowError) as exc: + raise validation_error("Invalid checkpoint voice selection") from exc diff --git a/src/deixicpublic/v1/sdk_pb2.py b/src/deixicpublic/v1/sdk_pb2.py index bcfadd6..202dfcc 100644 --- a/src/deixicpublic/v1/sdk_pb2.py +++ b/src/deixicpublic/v1/sdk_pb2.py @@ -25,7 +25,7 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x64\x65ixicpublic/v1/sdk.proto\x12\x0f\x64\x65ixicpublic.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"S\n\x05Scope\x12\'\n\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12!\n\x0cworkspace_id\x18\x02 \x01(\tR\x0bworkspaceId\"x\n\x0b\x45rrorDetail\x12\x12\n\x04\x63ode\x18\x01 \x01(\tR\x04\x63ode\x12\x18\n\x07message\x18\x02 \x01(\tR\x07message\x12\x1d\n\nrequest_id\x18\x03 \x01(\tR\trequestId\x12\x1c\n\tretryable\x18\x04 \x01(\x08R\tretryable\"\xd0\x04\n\x08TaskTurn\x12\x17\n\x07turn_id\x18\x01 \x01(\tR\x06turnId\x12\x1a\n\x08sequence\x18\x02 \x01(\x03R\x08sequence\x12&\n\x0fuser_message_id\x18\x03 \x01(\tR\ruserMessageId\x12\x30\n\x14\x61ssistant_message_id\x18\x04 \x01(\tR\x12\x61ssistantMessageId\x12\x30\n\x05state\x18\x05 \x01(\x0e\x32\x1a.deixicpublic.v1.TurnStateR\x05state\x12\x45\n\x0ewaiting_reason\x18\x06 \x01(\x0e\x32\x1e.deixicpublic.v1.WaitingReasonR\rwaitingReason\x12!\n\x0c\x66irst_cursor\x18\x07 \x01(\x03R\x0b\x66irstCursor\x12\x1f\n\x0blast_cursor\x18\x08 \x01(\x03R\nlastCursor\x12\x43\n\x0eterminal_error\x18\t \x01(\x0b\x32\x1c.deixicpublic.v1.ErrorDetailR\rterminalError\x12\x39\n\ncreated_at\x18\n \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x39\n\nupdated_at\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12=\n\x0c\x63ompleted_at\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x0b\x63ompletedAt\"\x9e\x02\n\x06Thread\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n\x05title\x18\x02 \x01(\tR\x05title\x12#\n\rreplay_cursor\x18\x03 \x01(\x03R\x0creplayCursor\x12\x30\n\x14\x61\x63tive_turn_sequence\x18\x04 \x01(\x03R\x12\x61\x63tiveTurnSequence\x12\x39\n\nupdated_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12!\n\x0cunread_count\x18\x06 \x01(\x05R\x0bunreadCount\x12\x1d\n\nopen_count\x18\x07 \x01(\x05R\topenCount\x12\x1a\n\x08\x61rchived\x18\x08 \x01(\x08R\x08\x61rchived\"\xbf\x01\n\x0bTaskMessage\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x30\n\x04role\x18\x02 \x01(\x0e\x32\x1c.deixicpublic.v1.MessageRoleR\x04role\x12\x12\n\x04\x62ody\x18\x03 \x01(\tR\x04\x62ody\x12\x39\n\ncreated_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x1f\n\x0breceipt_ids\x18\x05 \x03(\tR\nreceiptIds\"_\n\x11\x45videnceReference\x12\x12\n\x04kind\x18\x01 \x01(\tR\x04kind\x12\x0e\n\x02id\x18\x02 \x01(\tR\x02id\x12\x14\n\x05label\x18\x03 \x01(\tR\x05label\x12\x10\n\x03uri\x18\x04 \x01(\tR\x03uri\"\xe6\x03\n\tTaskEvent\x12\x16\n\x06\x63ursor\x18\x01 \x01(\x03R\x06\x63ursor\x12\x0e\n\x02id\x18\x02 \x01(\tR\x02id\x12\x17\n\x07turn_id\x18\x03 \x01(\tR\x06turnId\x12.\n\x04kind\x18\x04 \x01(\x0e\x32\x1a.deixicpublic.v1.EventKindR\x04kind\x12\x12\n\x04text\x18\x05 \x01(\tR\x04text\x12>\n\x08\x65vidence\x18\x06 \x03(\x0b\x32\".deixicpublic.v1.EvidenceReferenceR\x08\x65vidence\x12\x39\n\ncreated_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x1d\n\nrequest_id\x18\x08 \x01(\tR\trequestId\x12?\n\x0crequest_kind\x18\t \x01(\x0e\x32\x1c.deixicpublic.v1.RequestKindR\x0brequestKind\x12\x1b\n\ttool_name\x18\n \x01(\tR\x08toolName\x12\x17\n\x07\x63\x61ll_id\x18\x0b \x01(\tR\x06\x63\x61llId\x12\x43\n\x0eterminal_error\x18\x0c \x01(\x0b\x32\x1c.deixicpublic.v1.ErrorDetailR\rterminalError\"\xa7\x01\n\rReceiptAction\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n\x05label\x18\x02 \x01(\tR\x05label\x12\x12\n\x04kind\x18\x03 \x01(\tR\x04kind\x12\x33\n\x15requires_confirmation\x18\x04 \x01(\x08R\x14requiresConfirmation\x12\'\n\x0f\x64isabled_reason\x18\x05 \x01(\tR\x0e\x64isabledReason\"\xaf\x01\n\x0c\x43odingOutput\x12\x12\n\x04path\x18\x01 \x01(\tR\x04path\x12\x1b\n\tobject_id\x18\x02 \x01(\tR\x08objectId\x12\x1d\n\nversion_id\x18\x03 \x01(\tR\tversionId\x12\x16\n\x06sha256\x18\x04 \x01(\tR\x06sha256\x12\x1d\n\nsize_bytes\x18\x05 \x01(\x04R\tsizeBytes\x12\x18\n\x07\x63ontent\x18\x06 \x01(\x0cR\x07\x63ontent\"\xf3\x01\n\x10\x43odingAcceptance\x12\x1a\n\x08\x61\x63\x63\x65pted\x18\x01 \x01(\x08R\x08\x61\x63\x63\x65pted\x12\'\n\x0f\x63ontract_digest\x18\x02 \x01(\tR\x0e\x63ontractDigest\x12+\n\x11submission_digest\x18\x03 \x01(\tR\x10submissionDigest\x12\x18\n\x07reasons\x18\x04 \x03(\tR\x07reasons\x12\x1a\n\x08revision\x18\x05 \x01(\tR\x08revision\x12\x37\n\x07outputs\x18\x06 \x03(\x0b\x32\x1d.deixicpublic.v1.CodingOutputR\x07outputs\"\xa6\x03\n\x07Receipt\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n\x04kind\x18\x02 \x01(\tR\x04kind\x12\x14\n\x05title\x18\x03 \x01(\tR\x05title\x12\x18\n\x07summary\x18\x04 \x01(\tR\x07summary\x12\x33\n\x05state\x18\x05 \x01(\x0e\x32\x1d.deixicpublic.v1.ReceiptStateR\x05state\x12\x39\n\nupdated_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12G\n\x0f\x61llowed_actions\x18\x07 \x03(\x0b\x32\x1e.deixicpublic.v1.ReceiptActionR\x0e\x61llowedActions\x12>\n\x08\x65vidence\x18\x08 \x03(\x0b\x32\".deixicpublic.v1.EvidenceReferenceR\x08\x65vidence\x12N\n\x11\x63oding_acceptance\x18\t \x01(\x0b\x32!.deixicpublic.v1.CodingAcceptanceR\x10\x63odingAcceptance\"B\n\x0eModelSelection\x12\x1a\n\x08provider\x18\x01 \x01(\tR\x08provider\x12\x14\n\x05model\x18\x02 \x01(\tR\x05model\"{\n\x0e\x41vailableModel\x12\x1a\n\x08provider\x18\x01 \x01(\tR\x08provider\x12\x14\n\x05model\x18\x02 \x01(\tR\x05model\x12\x14\n\x05ready\x18\x03 \x01(\x08R\x05ready\x12!\n\x0c\x64isplay_name\x18\x04 \x01(\tR\x0b\x64isplayName\"\xd5\x02\n\x0eSetupReadiness\x12\x1e\n\naccessible\x18\x01 \x01(\x08R\naccessible\x12\x31\n\x14missing_requirements\x18\x02 \x03(\tR\x13missingRequirements\x12=\n\tselection\x18\x03 \x01(\x0b\x32\x1f.deixicpublic.v1.ModelSelectionR\tselection\x12\x44\n\rdefault_model\x18\x04 \x01(\x0b\x32\x1f.deixicpublic.v1.AvailableModelR\x0c\x64\x65\x66\x61ultModel\x12J\n\x10\x61vailable_models\x18\x05 \x03(\x0b\x32\x1f.deixicpublic.v1.AvailableModelR\x0f\x61vailableModels\x12\x1f\n\x0bnext_action\x18\x06 \x01(\tR\nnextAction\"\xa9\x01\n\x18GetModelReadinessRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12=\n\tselection\x18\x02 \x01(\x0b\x32\x1f.deixicpublic.v1.ModelSelectionR\tselection\x12 \n\x0b\x65nvironment\x18\x03 \x01(\tR\x0b\x65nvironment\"\xea\x02\n\x19GetModelReadinessResponse\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12=\n\tselection\x18\x02 \x01(\x0b\x32\x1f.deixicpublic.v1.ModelSelectionR\tselection\x12 \n\x0b\x65nvironment\x18\x03 \x01(\tR\x0b\x65nvironment\x12:\n\x05state\x18\x04 \x01(\x0e\x32$.deixicpublic.v1.ModelReadinessStateR\x05state\x12\x43\n\x0cnext_actions\x18\x05 \x03(\x0e\x32 .deixicpublic.v1.ModelNextActionR\x0bnextActions\x12=\n\x0c\x65valuated_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x0b\x65valuatedAt\"\x8f\x01\n\nClientRule\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n\x05title\x18\x02 \x01(\tR\x05title\x12#\n\rbody_markdown\x18\x03 \x01(\tR\x0c\x62odyMarkdown\x12\x36\n\x05scope\x18\x04 \x01(\x0e\x32 .deixicpublic.v1.ClientRuleScopeR\x05scope\"k\n\x0b\x43lientSkill\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x16\n\x06source\x18\x02 \x01(\tR\x06source\x12\x18\n\x07version\x18\x03 \x01(\tR\x07version\x12\x1a\n\x08required\x18\x04 \x01(\x08R\x08required\"d\n\x0f\x43lientMcpServer\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\x12\x1f\n\x0burl_pattern\x18\x02 \x01(\tR\nurlPattern\x12\x1c\n\ttransport\x18\x03 \x01(\tR\ttransport\"\x81\x01\n\x0f\x43lientMcpPolicy\x12\x32\n\x04mode\x18\x01 \x01(\x0e\x32\x1e.deixicpublic.v1.ClientMcpModeR\x04mode\x12:\n\x07servers\x18\x02 \x03(\x0b\x32 .deixicpublic.v1.ClientMcpServerR\x07servers\"E\n\x15GetClientSetupRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\"\xe6\x02\n\x16GetClientSetupResponse\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x18\n\x07version\x18\x02 \x01(\x04R\x07version\x12\x37\n\tissued_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x08issuedAt\x12\x31\n\x05rules\x18\x04 \x03(\x0b\x32\x1b.deixicpublic.v1.ClientRuleR\x05rules\x12\x34\n\x06skills\x18\x05 \x03(\x0b\x32\x1c.deixicpublic.v1.ClientSkillR\x06skills\x12\x32\n\x03mcp\x18\x06 \x01(\x0b\x32 .deixicpublic.v1.ClientMcpPolicyR\x03mcp\x12.\n\x13sandbox_policy_toml\x18\x07 \x01(\tR\x11sandboxPolicyToml\"T\n\rIssueEvidence\x12\x12\n\x04kind\x18\x01 \x01(\tR\x04kind\x12\x1b\n\tsource_id\x18\x02 \x01(\tR\x08sourceId\x12\x12\n\x04text\x18\x03 \x01(\tR\x04text\"\x8f\x01\n\x0cIssueContext\x12-\n\x12reproduction_steps\x18\x01 \x01(\tR\x11reproductionSteps\x12\x14\n\x05model\x18\x02 \x01(\tR\x05model\x12:\n\x08\x65vidence\x18\x03 \x03(\x0b\x32\x1e.deixicpublic.v1.IssueEvidenceR\x08\x65vidence\"\xcb\x02\n\x18SubmitIssueReportRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12 \n\x0b\x64\x65scription\x18\x02 \x01(\tR\x0b\x64\x65scription\x12+\n\x11\x65xpected_behavior\x18\x03 \x01(\tR\x10\x65xpectedBehavior\x12\x1f\n\x0b\x61pp_version\x18\x04 \x01(\tR\nappVersion\x12/\n\x13include_diagnostics\x18\x05 \x01(\x08R\x12includeDiagnostics\x12\'\n\x0fidempotency_key\x18\x06 \x01(\tR\x0eidempotencyKey\x12\x37\n\x07\x63ontext\x18\x07 \x01(\x0b\x32\x1d.deixicpublic.v1.IssueContextR\x07\x63ontext\";\n\x0bIssueReport\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x1c\n\treference\x18\x02 \x01(\tR\treference\"Q\n\x19SubmitIssueReportResponse\x12\x34\n\x06report\x18\x01 \x01(\x0b\x32\x1c.deixicpublic.v1.IssueReportR\x06report\"C\n\rBusinessMoney\x12\x16\n\x06\x61mount\x18\x01 \x01(\tR\x06\x61mount\x12\x1a\n\x08\x63urrency\x18\x02 \x01(\tR\x08\x63urrency\"6\n\x17\x42usinessObjectReference\x12\x1b\n\tobject_id\x18\x01 \x01(\tR\x08objectId\"K\n\x19\x42usinessArtifactReference\x12.\n\x13\x61rtifact_version_id\x18\x01 \x01(\tR\x11\x61rtifactVersionId\"*\n\x10\x42usinessTextList\x12\x16\n\x06values\x18\x01 \x03(\tR\x06values\"\x87\x04\n\x12\x42usinessFieldValue\x12\x19\n\x08\x66ield_id\x18\x01 \x01(\tR\x07\x66ieldId\x12\x14\n\x04text\x18\x02 \x01(\tH\x00R\x04text\x12\x1a\n\x07integer\x18\x03 \x01(\x03H\x00R\x07integer\x12\x1a\n\x07\x62oolean\x18\x04 \x01(\x08H\x00R\x07\x62oolean\x12\x1a\n\x07\x64\x65\x63imal\x18\x05 \x01(\tH\x00R\x07\x64\x65\x63imal\x12\x36\n\x05money\x18\x06 \x01(\x0b\x32\x1e.deixicpublic.v1.BusinessMoneyH\x00R\x05money\x12\x1f\n\nenum_value\x18\x07 \x01(\tH\x00R\tenumValue\x12\x14\n\x04\x64\x61te\x18\x08 \x01(\tH\x00R\x04\x64\x61te\x12\x1e\n\ttimestamp\x18\t \x01(\tH\x00R\ttimestamp\x12H\n\treference\x18\n \x01(\x0b\x32(.deixicpublic.v1.BusinessObjectReferenceH\x00R\treference\x12H\n\x08\x61rtifact\x18\x0b \x01(\x0b\x32*.deixicpublic.v1.BusinessArtifactReferenceH\x00R\x08\x61rtifact\x12@\n\ttext_list\x18\x0c \x01(\x0b\x32!.deixicpublic.v1.BusinessTextListH\x00R\x08textListB\x07\n\x05value\"\xac\x02\n\x0e\x42usinessObject\x12\x1b\n\tobject_id\x18\x01 \x01(\tR\x08objectId\x12\x17\n\x07type_id\x18\x02 \x01(\tR\x06typeId\x12\'\n\x0fschema_revision\x18\x03 \x01(\x03R\x0eschemaRevision\x12\x1a\n\x08revision\x18\x04 \x01(\x03R\x08revision\x12;\n\x06values\x18\x05 \x03(\x0b\x32#.deixicpublic.v1.BusinessFieldValueR\x06values\x12\x18\n\x07\x64\x65leted\x18\x06 \x01(\x08R\x07\x64\x65leted\x12\x1d\n\nupdated_at\x18\t \x01(\tR\tupdatedAt\x12\x1d\n\ncreated_at\x18\n \x01(\tR\tcreatedAtJ\x04\x08\x07\x10\x08J\x04\x08\x08\x10\t\"\x91\x02\n\x1b\x43reateBusinessObjectRequest\x12\'\n\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12!\n\x0cworkspace_id\x18\x02 \x01(\tR\x0bworkspaceId\x12\'\n\x0fidempotency_key\x18\x03 \x01(\tR\x0eidempotencyKey\x12\x17\n\x07type_id\x18\x04 \x01(\tR\x06typeId\x12\'\n\x0fschema_revision\x18\x05 \x01(\x03R\x0eschemaRevision\x12;\n\x06values\x18\x06 \x03(\x0b\x32#.deixicpublic.v1.BusinessFieldValueR\x06values\"W\n\x1c\x43reateBusinessObjectResponse\x12\x37\n\x06object\x18\x01 \x01(\x0b\x32\x1f.deixicpublic.v1.BusinessObjectR\x06object\"\x8f\x01\n\x18GetBusinessObjectRequest\x12\'\n\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12!\n\x0cworkspace_id\x18\x02 \x01(\tR\x0bworkspaceId\x12\x1b\n\tobject_id\x18\x04 \x01(\tR\x08objectIdJ\x04\x08\x03\x10\x04J\x04\x08\x05\x10\x06\"T\n\x19GetBusinessObjectResponse\x12\x37\n\x06object\x18\x01 \x01(\x0b\x32\x1f.deixicpublic.v1.BusinessObjectR\x06object\"\xc2\x02\n\x1bUpdateBusinessObjectRequest\x12\'\n\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12!\n\x0cworkspace_id\x18\x02 \x01(\tR\x0bworkspaceId\x12\'\n\x0fidempotency_key\x18\x03 \x01(\tR\x0eidempotencyKey\x12\x1b\n\tobject_id\x18\x04 \x01(\tR\x08objectId\x12+\n\x11\x65xpected_revision\x18\x05 \x01(\x03R\x10\x65xpectedRevision\x12;\n\x06values\x18\x06 \x03(\x0b\x32#.deixicpublic.v1.BusinessFieldValueR\x06values\x12\'\n\x0fschema_revision\x18\x07 \x01(\x03R\x0eschemaRevision\"W\n\x1cUpdateBusinessObjectResponse\x12\x37\n\x06object\x18\x01 \x01(\x0b\x32\x1f.deixicpublic.v1.BusinessObjectR\x06object\"\xdc\x01\n\x1b\x44\x65leteBusinessObjectRequest\x12\'\n\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12!\n\x0cworkspace_id\x18\x02 \x01(\tR\x0bworkspaceId\x12\'\n\x0fidempotency_key\x18\x03 \x01(\tR\x0eidempotencyKey\x12\x1b\n\tobject_id\x18\x04 \x01(\tR\x08objectId\x12+\n\x11\x65xpected_revision\x18\x05 \x01(\x03R\x10\x65xpectedRevision\"W\n\x1c\x44\x65leteBusinessObjectResponse\x12\x37\n\x06object\x18\x01 \x01(\x0b\x32\x1f.deixicpublic.v1.BusinessObjectR\x06object\"\x92\x01\n\x10GetThreadRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12\x14\n\x05limit\x18\x03 \x01(\x05R\x05limit\x12\x1d\n\npage_token\x18\x04 \x01(\tR\tpageToken\"\xe9\x02\n\x11GetThreadResponse\x12/\n\x06thread\x18\x01 \x01(\x0b\x32\x17.deixicpublic.v1.ThreadR\x06thread\x12\x38\n\x08messages\x18\x02 \x03(\x0b\x32\x1c.deixicpublic.v1.TaskMessageR\x08messages\x12\x34\n\x08receipts\x18\x03 \x03(\x0b\x32\x18.deixicpublic.v1.ReceiptR\x08receipts\x12/\n\x05turns\x18\x04 \x03(\x0b\x32\x19.deixicpublic.v1.TaskTurnR\x05turns\x12#\n\rreplay_cursor\x18\x05 \x01(\x03R\x0creplayCursor\x12&\n\x0fnext_page_token\x18\x06 \x01(\tR\rnextPageToken\x12\x35\n\x05setup\x18\x07 \x01(\x0b\x32\x1f.deixicpublic.v1.SetupReadinessR\x05setup\"^\n\x12ListThreadsRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1a\n\x08\x61rchived\x18\x02 \x01(\x08R\x08\x61rchived\"H\n\x13ListThreadsResponse\x12\x31\n\x07threads\x18\x01 \x03(\x0b\x32\x17.deixicpublic.v1.ThreadR\x07threads\"v\n\x13RenameThreadRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12\x14\n\x05title\x18\x03 \x01(\tR\x05title\"a\n\x14RenameThreadResponse\x12/\n\x06thread\x18\x01 \x01(\x0b\x32\x17.deixicpublic.v1.ThreadR\x06thread\x12\x18\n\x07\x63hanged\x18\x02 \x01(\x08R\x07\x63hanged\"\xa6\x01\n\x14\x41rchiveThreadRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12\x1a\n\x08\x61rchived\x18\x03 \x01(\x08R\x08\x61rchived\x12\'\n\x0fidempotency_key\x18\x04 \x01(\tR\x0eidempotencyKey\"~\n\x15\x41rchiveThreadResponse\x12/\n\x06thread\x18\x01 \x01(\x0b\x32\x17.deixicpublic.v1.ThreadR\x06thread\x12\x18\n\x07\x63hanged\x18\x02 \x01(\x08R\x07\x63hanged\x12\x1a\n\x08replayed\x18\x03 \x01(\x08R\x08replayed\"\x97\x01\n\x11ListEventsRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12!\n\x0c\x61\x66ter_cursor\x18\x03 \x01(\x03R\x0b\x61\x66terCursor\x12\x14\n\x05limit\x18\x04 \x01(\x05R\x05limit\"\xa2\x02\n\x12ListEventsResponse\x12\x32\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x1a.deixicpublic.v1.TaskEventR\x06\x65vents\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\x03R\nnextCursor\x12\x19\n\x08has_more\x18\x03 \x01(\x08R\x07hasMore\x12%\n\x0ereset_required\x18\x04 \x01(\x08R\rresetRequired\x12\x33\n\x08snapshot\x18\x05 \x01(\x0b\x32\x17.deixicpublic.v1.ThreadR\x08snapshot\x12@\n\x0esnapshot_turns\x18\x06 \x03(\x0b\x32\x19.deixicpublic.v1.TaskTurnR\rsnapshotTurns\"\x82\x01\n\x12WatchEventsRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12!\n\x0c\x61\x66ter_cursor\x18\x03 \x01(\x03R\x0b\x61\x66terCursor\"\x88\x02\n\x13WatchEventsResponse\x12\x32\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x1a.deixicpublic.v1.TaskEventR\x06\x65vents\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\x03R\nnextCursor\x12%\n\x0ereset_required\x18\x03 \x01(\x08R\rresetRequired\x12\x33\n\x08snapshot\x18\x04 \x01(\x0b\x32\x17.deixicpublic.v1.ThreadR\x08snapshot\x12@\n\x0esnapshot_turns\x18\x05 \x03(\x0b\x32\x19.deixicpublic.v1.TaskTurnR\rsnapshotTurns\"\x9b\x03\n\x0e\x43odingContract\x12#\n\rrepository_id\x18\x01 \x01(\tR\x0crepositoryId\x12\x1e\n\ngeneration\x18\x02 \x01(\x04R\ngeneration\x12\x34\n\x16required_assertion_ids\x18\x03 \x03(\tR\x14requiredAssertionIds\x12%\n\x0erequire_review\x18\x04 \x01(\x08R\rrequireReview\x12)\n\x10require_behavior\x18\x05 \x01(\x08R\x0frequireBehavior\x12\x35\n\x16readiness_requirements\x18\x06 \x03(\tR\x15readinessRequirements\x12)\n\x10\x61uthorized_skips\x18\x07 \x03(\tR\x0f\x61uthorizedSkips\x12\x37\n\x17\x61uthorized_dispositions\x18\x08 \x03(\tR\x16\x61uthorizedDispositions\x12!\n\x0coutput_paths\x18\t \x03(\tR\x0boutputPaths\"\xbf\x03\n\x11SubmitTaskRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12\x12\n\x04\x62ody\x18\x03 \x01(\tR\x04\x62ody\x12\'\n\x0fidempotency_key\x18\x04 \x01(\tR\x0eidempotencyKey\x12\x30\n\x14\x63ontinuation_task_id\x18\x05 \x01(\tR\x12\x63ontinuationTaskId\x12,\n\x12reference_task_ids\x18\x06 \x03(\tR\x10referenceTaskIds\x12H\n\x0fmodel_selection\x18\x07 \x01(\x0b\x32\x1f.deixicpublic.v1.ModelSelectionR\x0emodelSelection\x12H\n\x0f\x63oding_contract\x18\x08 \x01(\x0b\x32\x1f.deixicpublic.v1.CodingContractR\x0e\x63odingContract\x12.\n\x13project_resource_id\x18\t \x01(\tR\x11projectResourceId\"\xe7\x01\n\x12SubmitTaskResponse\x12\x36\n\x07message\x18\x01 \x01(\x0b\x32\x1c.deixicpublic.v1.TaskMessageR\x07message\x12>\n\raccepted_turn\x18\x02 \x01(\x0b\x32\x19.deixicpublic.v1.TaskTurnR\x0c\x61\x63\x63\x65ptedTurn\x12#\n\rreplay_cursor\x18\x03 \x01(\x03R\x0creplayCursor\x12\x34\n\x08receipts\x18\x04 \x03(\x0b\x32\x18.deixicpublic.v1.ReceiptR\x08receipts\"\xbb\x01\n\x14InterruptTaskRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12\x17\n\x07turn_id\x18\x03 \x01(\tR\x06turnId\x12\'\n\x0fidempotency_key\x18\x04 \x01(\tR\x0eidempotencyKey\x12\x16\n\x06reason\x18\x05 \x01(\tR\x06reason\"\xa2\x01\n\x15InterruptTaskResponse\x12\x17\n\x07turn_id\x18\x01 \x01(\tR\x06turnId\x12\x1a\n\x08replayed\x18\x02 \x01(\x08R\x08replayed\x12/\n\x05turns\x18\x03 \x03(\x0b\x32\x19.deixicpublic.v1.TaskTurnR\x05turns\x12#\n\rreplay_cursor\x18\x04 \x01(\x03R\x0creplayCursor\"\x87\x03\n\x17RespondToRequestRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12\x17\n\x07turn_id\x18\x03 \x01(\tR\x06turnId\x12\x1d\n\nrequest_id\x18\x04 \x01(\tR\trequestId\x12\x17\n\x07\x63\x61ll_id\x18\x05 \x01(\tR\x06\x63\x61llId\x12?\n\x0crequest_kind\x18\x06 \x01(\x0e\x32\x1c.deixicpublic.v1.RequestKindR\x0brequestKind\x12\x37\n\x06\x61\x63tion\x18\x07 \x01(\x0e\x32\x1f.deixicpublic.v1.ResponseActionR\x06\x61\x63tion\x12\x12\n\x04text\x18\x08 \x01(\tR\x04text\x12\x19\n\x08is_error\x18\t \x01(\x08R\x07isError\x12\'\n\x0fidempotency_key\x18\n \x01(\tR\x0eidempotencyKey\"\x8c\x01\n\x18RespondToRequestResponse\x12\x1a\n\x08replayed\x18\x01 \x01(\x08R\x08replayed\x12/\n\x05turns\x18\x02 \x03(\x0b\x32\x19.deixicpublic.v1.TaskTurnR\x05turns\x12#\n\rreplay_cursor\x18\x03 \x01(\x03R\x0creplayCursor\"\xc0\x01\n\x11GetReceiptRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1d\n\nreceipt_id\x18\x02 \x01(\tR\treceiptId\x12\x1b\n\tthread_id\x18\x03 \x01(\tR\x08threadId\x12\x41\n\x1dinclude_coding_output_content\x18\x04 \x01(\x08R\x1aincludeCodingOutputContent\"H\n\x12GetReceiptResponse\x12\x32\n\x07receipt\x18\x01 \x01(\x0b\x32\x18.deixicpublic.v1.ReceiptR\x07receipt\"\xb0\x01\n\x1bResolveReceiptActionRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1d\n\nreceipt_id\x18\x02 \x01(\tR\treceiptId\x12\x1b\n\taction_id\x18\x03 \x01(\tR\x08\x61\x63tionId\x12\'\n\x0fidempotency_key\x18\x04 \x01(\tR\x0eidempotencyKey\"R\n\x1cResolveReceiptActionResponse\x12\x32\n\x07receipt\x18\x01 \x01(\x0b\x32\x18.deixicpublic.v1.ReceiptR\x07receipt*\xd7\x01\n\tTurnState\x12\x1a\n\x16TURN_STATE_UNSPECIFIED\x10\x00\x12\x17\n\x13TURN_STATE_ACCEPTED\x10\x01\x12\x16\n\x12TURN_STATE_RUNNING\x10\x02\x12\x16\n\x12TURN_STATE_WAITING\x10\x03\x12\x18\n\x14TURN_STATE_RESPONDED\x10\x04\x12\x18\n\x14TURN_STATE_COMPLETED\x10\x05\x12\x15\n\x11TURN_STATE_FAILED\x10\x06\x12\x1a\n\x16TURN_STATE_INTERRUPTED\x10\x07*\xae\x01\n\rWaitingReason\x12\x1e\n\x1aWAITING_REASON_UNSPECIFIED\x10\x00\x12\x1b\n\x17WAITING_REASON_APPROVAL\x10\x01\x12\x1d\n\x19WAITING_REASON_USER_INPUT\x10\x02\x12\x1e\n\x1aWAITING_REASON_CLIENT_TOOL\x10\x03\x12!\n\x1dWAITING_REASON_EXTERNAL_RETRY\x10\x04*w\n\x0bMessageRole\x12\x1c\n\x18MESSAGE_ROLE_UNSPECIFIED\x10\x00\x12\x15\n\x11MESSAGE_ROLE_USER\x10\x01\x12\x1a\n\x16MESSAGE_ROLE_ASSISTANT\x10\x02\x12\x17\n\x13MESSAGE_ROLE_SYSTEM\x10\x03*\x9a\x04\n\tEventKind\x12\x1a\n\x16\x45VENT_KIND_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x45VENT_KIND_TURN_ACCEPTED\x10\x01\x12\x1b\n\x17\x45VENT_KIND_TURN_STARTED\x10\x02\x12\x17\n\x13\x45VENT_KIND_PROGRESS\x10\x03\x12 \n\x1c\x45VENT_KIND_APPROVAL_REQUIRED\x10\x04\x12\x1d\n\x19\x45VENT_KIND_INPUT_REQUIRED\x10\x05\x12 \n\x1c\x45VENT_KIND_ARTIFACT_RECORDED\x10\x06\x12\x1d\n\x19\x45VENT_KIND_TURN_COMPLETED\x10\x07\x12\x1a\n\x16\x45VENT_KIND_TURN_FAILED\x10\x08\x12\x1f\n\x1b\x45VENT_KIND_TURN_INTERRUPTED\x10\t\x12#\n\x1f\x45VENT_KIND_CLIENT_TOOL_REQUIRED\x10\n\x12&\n\"EVENT_KIND_EXTERNAL_RETRY_REQUIRED\x10\x0b\x12#\n\x1f\x45VENT_KIND_ASSISTANT_TEXT_DELTA\x10\x0c\x12&\n\"EVENT_KIND_ASSISTANT_TEXT_OBSERVED\x10\r\x12&\n\"EVENT_KIND_MODEL_ATTEMPT_ABANDONED\x10\x0e\x12\x1c\n\x18\x45VENT_KIND_TOOL_PROPOSED\x10\x0f*\xa2\x01\n\x0bRequestKind\x12\x1c\n\x18REQUEST_KIND_UNSPECIFIED\x10\x00\x12\x19\n\x15REQUEST_KIND_APPROVAL\x10\x01\x12\x1b\n\x17REQUEST_KIND_USER_INPUT\x10\x02\x12\x1c\n\x18REQUEST_KIND_CLIENT_TOOL\x10\x03\x12\x1f\n\x1bREQUEST_KIND_EXTERNAL_RETRY\x10\x04*\xa0\x03\n\x0cReceiptState\x12\x1d\n\x19RECEIPT_STATE_UNSPECIFIED\x10\x00\x12\x19\n\x15RECEIPT_STATE_UNKNOWN\x10\x01\x12\x1a\n\x16RECEIPT_STATE_PROPOSED\x10\x02\x12\x18\n\x14RECEIPT_STATE_QUEUED\x10\x03\x12\"\n\x1eRECEIPT_STATE_WAITING_APPROVAL\x10\x04\x12\x19\n\x15RECEIPT_STATE_BLOCKED\x10\x05\x12\x1d\n\x19RECEIPT_STATE_NEEDS_INPUT\x10\x06\x12\x1d\n\x19RECEIPT_STATE_UNAVAILABLE\x10\x07\x12\x19\n\x15RECEIPT_STATE_RUNNING\x10\x08\x12\x1b\n\x17RECEIPT_STATE_SUCCEEDED\x10\t\x12\x1a\n\x16RECEIPT_STATE_VERIFIED\x10\n\x12\x18\n\x14RECEIPT_STATE_DENIED\x10\x0b\x12\x1b\n\x17RECEIPT_STATE_CANCELLED\x10\x0c\x12\x18\n\x14RECEIPT_STATE_FAILED\x10\r*\xc0\x02\n\x13ModelReadinessState\x12%\n!MODEL_READINESS_STATE_UNSPECIFIED\x10\x00\x12\x1f\n\x1bMODEL_READINESS_STATE_READY\x10\x01\x12-\n)MODEL_READINESS_STATE_ACTIVATION_REQUIRED\x10\x02\x12*\n&MODEL_READINESS_STATE_FUNDING_REQUIRED\x10\x03\x12\'\n#MODEL_READINESS_STATE_LIMIT_REACHED\x10\x04\x12*\n&MODEL_READINESS_STATE_ACCESS_SUSPENDED\x10\x05\x12\x31\n-MODEL_READINESS_STATE_TEMPORARILY_UNAVAILABLE\x10\x06*\xa2\x01\n\x0fModelNextAction\x12!\n\x1dMODEL_NEXT_ACTION_UNSPECIFIED\x10\x00\x12+\n\'MODEL_NEXT_ACTION_CONTACT_ADMINISTRATOR\x10\x01\x12\"\n\x1eMODEL_NEXT_ACTION_VIEW_FUNDING\x10\x02\x12\x1b\n\x17MODEL_NEXT_ACTION_RETRY\x10\x03*y\n\x0f\x43lientRuleScope\x12!\n\x1d\x43LIENT_RULE_SCOPE_UNSPECIFIED\x10\x00\x12\"\n\x1e\x43LIENT_RULE_SCOPE_ORGANIZATION\x10\x01\x12\x1f\n\x1b\x43LIENT_RULE_SCOPE_WORKSPACE\x10\x02*\x87\x01\n\rClientMcpMode\x12\x1f\n\x1b\x43LIENT_MCP_MODE_UNSPECIFIED\x10\x00\x12\x18\n\x14\x43LIENT_MCP_MODE_OPEN\x10\x01\x12\x1d\n\x19\x43LIENT_MCP_MODE_ALLOWLIST\x10\x02\x12\x1c\n\x18\x43LIENT_MCP_MODE_DENYLIST\x10\x03*\xd4\x01\n\x0eResponseAction\x12\x1f\n\x1bRESPONSE_ACTION_UNSPECIFIED\x10\x00\x12\x1b\n\x17RESPONSE_ACTION_APPROVE\x10\x01\x12\x18\n\x14RESPONSE_ACTION_DENY\x10\x02\x12\x1a\n\x16RESPONSE_ACTION_ANSWER\x10\x03\x12\x19\n\x15RESPONSE_ACTION_RETRY\x10\x04\x12\x18\n\x14RESPONSE_ACTION_SKIP\x10\x05\x12\x19\n\x15RESPONSE_ACTION_ABORT\x10\x06\x32\xa5\x0e\n\x13\x44\x65ixicPublicService\x12R\n\tGetThread\x12!.deixicpublic.v1.GetThreadRequest\x1a\".deixicpublic.v1.GetThreadResponse\x12X\n\x0bListThreads\x12#.deixicpublic.v1.ListThreadsRequest\x1a$.deixicpublic.v1.ListThreadsResponse\x12[\n\x0cRenameThread\x12$.deixicpublic.v1.RenameThreadRequest\x1a%.deixicpublic.v1.RenameThreadResponse\x12^\n\rArchiveThread\x12%.deixicpublic.v1.ArchiveThreadRequest\x1a&.deixicpublic.v1.ArchiveThreadResponse\x12U\n\nListEvents\x12\".deixicpublic.v1.ListEventsRequest\x1a#.deixicpublic.v1.ListEventsResponse\x12Z\n\x0bWatchEvents\x12#.deixicpublic.v1.WatchEventsRequest\x1a$.deixicpublic.v1.WatchEventsResponse0\x01\x12U\n\nSubmitTask\x12\".deixicpublic.v1.SubmitTaskRequest\x1a#.deixicpublic.v1.SubmitTaskResponse\x12^\n\rInterruptTask\x12%.deixicpublic.v1.InterruptTaskRequest\x1a&.deixicpublic.v1.InterruptTaskResponse\x12g\n\x10RespondToRequest\x12(.deixicpublic.v1.RespondToRequestRequest\x1a).deixicpublic.v1.RespondToRequestResponse\x12U\n\nGetReceipt\x12\".deixicpublic.v1.GetReceiptRequest\x1a#.deixicpublic.v1.GetReceiptResponse\x12s\n\x14ResolveReceiptAction\x12,.deixicpublic.v1.ResolveReceiptActionRequest\x1a-.deixicpublic.v1.ResolveReceiptActionResponse\x12j\n\x11GetModelReadiness\x12).deixicpublic.v1.GetModelReadinessRequest\x1a*.deixicpublic.v1.GetModelReadinessResponse\x12\x61\n\x0eGetClientSetup\x12&.deixicpublic.v1.GetClientSetupRequest\x1a\'.deixicpublic.v1.GetClientSetupResponse\x12j\n\x11SubmitIssueReport\x12).deixicpublic.v1.SubmitIssueReportRequest\x1a*.deixicpublic.v1.SubmitIssueReportResponse\x12s\n\x14\x43reateBusinessObject\x12,.deixicpublic.v1.CreateBusinessObjectRequest\x1a-.deixicpublic.v1.CreateBusinessObjectResponse\x12j\n\x11GetBusinessObject\x12).deixicpublic.v1.GetBusinessObjectRequest\x1a*.deixicpublic.v1.GetBusinessObjectResponse\x12s\n\x14UpdateBusinessObject\x12,.deixicpublic.v1.UpdateBusinessObjectRequest\x1a-.deixicpublic.v1.UpdateBusinessObjectResponse\x12s\n\x14\x44\x65leteBusinessObject\x12,.deixicpublic.v1.DeleteBusinessObjectRequest\x1a-.deixicpublic.v1.DeleteBusinessObjectResponseB=Z;github.com/dx-corp/deixic-go/deixicpublic/v1;deixicpublicv1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x64\x65ixicpublic/v1/sdk.proto\x12\x0f\x64\x65ixicpublic.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"S\n\x05Scope\x12\'\n\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12!\n\x0cworkspace_id\x18\x02 \x01(\tR\x0bworkspaceId\"x\n\x0b\x45rrorDetail\x12\x12\n\x04\x63ode\x18\x01 \x01(\tR\x04\x63ode\x12\x18\n\x07message\x18\x02 \x01(\tR\x07message\x12\x1d\n\nrequest_id\x18\x03 \x01(\tR\trequestId\x12\x1c\n\tretryable\x18\x04 \x01(\x08R\tretryable\"\xd0\x04\n\x08TaskTurn\x12\x17\n\x07turn_id\x18\x01 \x01(\tR\x06turnId\x12\x1a\n\x08sequence\x18\x02 \x01(\x03R\x08sequence\x12&\n\x0fuser_message_id\x18\x03 \x01(\tR\ruserMessageId\x12\x30\n\x14\x61ssistant_message_id\x18\x04 \x01(\tR\x12\x61ssistantMessageId\x12\x30\n\x05state\x18\x05 \x01(\x0e\x32\x1a.deixicpublic.v1.TurnStateR\x05state\x12\x45\n\x0ewaiting_reason\x18\x06 \x01(\x0e\x32\x1e.deixicpublic.v1.WaitingReasonR\rwaitingReason\x12!\n\x0c\x66irst_cursor\x18\x07 \x01(\x03R\x0b\x66irstCursor\x12\x1f\n\x0blast_cursor\x18\x08 \x01(\x03R\nlastCursor\x12\x43\n\x0eterminal_error\x18\t \x01(\x0b\x32\x1c.deixicpublic.v1.ErrorDetailR\rterminalError\x12\x39\n\ncreated_at\x18\n \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x39\n\nupdated_at\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12=\n\x0c\x63ompleted_at\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x0b\x63ompletedAt\"\x9e\x02\n\x06Thread\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n\x05title\x18\x02 \x01(\tR\x05title\x12#\n\rreplay_cursor\x18\x03 \x01(\x03R\x0creplayCursor\x12\x30\n\x14\x61\x63tive_turn_sequence\x18\x04 \x01(\x03R\x12\x61\x63tiveTurnSequence\x12\x39\n\nupdated_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12!\n\x0cunread_count\x18\x06 \x01(\x05R\x0bunreadCount\x12\x1d\n\nopen_count\x18\x07 \x01(\x05R\topenCount\x12\x1a\n\x08\x61rchived\x18\x08 \x01(\x08R\x08\x61rchived\"\xbf\x01\n\x0bTaskMessage\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x30\n\x04role\x18\x02 \x01(\x0e\x32\x1c.deixicpublic.v1.MessageRoleR\x04role\x12\x12\n\x04\x62ody\x18\x03 \x01(\tR\x04\x62ody\x12\x39\n\ncreated_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x1f\n\x0breceipt_ids\x18\x05 \x03(\tR\nreceiptIds\"_\n\x11\x45videnceReference\x12\x12\n\x04kind\x18\x01 \x01(\tR\x04kind\x12\x0e\n\x02id\x18\x02 \x01(\tR\x02id\x12\x14\n\x05label\x18\x03 \x01(\tR\x05label\x12\x10\n\x03uri\x18\x04 \x01(\tR\x03uri\"\xe6\x03\n\tTaskEvent\x12\x16\n\x06\x63ursor\x18\x01 \x01(\x03R\x06\x63ursor\x12\x0e\n\x02id\x18\x02 \x01(\tR\x02id\x12\x17\n\x07turn_id\x18\x03 \x01(\tR\x06turnId\x12.\n\x04kind\x18\x04 \x01(\x0e\x32\x1a.deixicpublic.v1.EventKindR\x04kind\x12\x12\n\x04text\x18\x05 \x01(\tR\x04text\x12>\n\x08\x65vidence\x18\x06 \x03(\x0b\x32\".deixicpublic.v1.EvidenceReferenceR\x08\x65vidence\x12\x39\n\ncreated_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12\x1d\n\nrequest_id\x18\x08 \x01(\tR\trequestId\x12?\n\x0crequest_kind\x18\t \x01(\x0e\x32\x1c.deixicpublic.v1.RequestKindR\x0brequestKind\x12\x1b\n\ttool_name\x18\n \x01(\tR\x08toolName\x12\x17\n\x07\x63\x61ll_id\x18\x0b \x01(\tR\x06\x63\x61llId\x12\x43\n\x0eterminal_error\x18\x0c \x01(\x0b\x32\x1c.deixicpublic.v1.ErrorDetailR\rterminalError\"\xa7\x01\n\rReceiptAction\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n\x05label\x18\x02 \x01(\tR\x05label\x12\x12\n\x04kind\x18\x03 \x01(\tR\x04kind\x12\x33\n\x15requires_confirmation\x18\x04 \x01(\x08R\x14requiresConfirmation\x12\'\n\x0f\x64isabled_reason\x18\x05 \x01(\tR\x0e\x64isabledReason\"\xaf\x01\n\x0c\x43odingOutput\x12\x12\n\x04path\x18\x01 \x01(\tR\x04path\x12\x1b\n\tobject_id\x18\x02 \x01(\tR\x08objectId\x12\x1d\n\nversion_id\x18\x03 \x01(\tR\tversionId\x12\x16\n\x06sha256\x18\x04 \x01(\tR\x06sha256\x12\x1d\n\nsize_bytes\x18\x05 \x01(\x04R\tsizeBytes\x12\x18\n\x07\x63ontent\x18\x06 \x01(\x0cR\x07\x63ontent\"\xf3\x01\n\x10\x43odingAcceptance\x12\x1a\n\x08\x61\x63\x63\x65pted\x18\x01 \x01(\x08R\x08\x61\x63\x63\x65pted\x12\'\n\x0f\x63ontract_digest\x18\x02 \x01(\tR\x0e\x63ontractDigest\x12+\n\x11submission_digest\x18\x03 \x01(\tR\x10submissionDigest\x12\x18\n\x07reasons\x18\x04 \x03(\tR\x07reasons\x12\x1a\n\x08revision\x18\x05 \x01(\tR\x08revision\x12\x37\n\x07outputs\x18\x06 \x03(\x0b\x32\x1d.deixicpublic.v1.CodingOutputR\x07outputs\"\xa6\x03\n\x07Receipt\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n\x04kind\x18\x02 \x01(\tR\x04kind\x12\x14\n\x05title\x18\x03 \x01(\tR\x05title\x12\x18\n\x07summary\x18\x04 \x01(\tR\x07summary\x12\x33\n\x05state\x18\x05 \x01(\x0e\x32\x1d.deixicpublic.v1.ReceiptStateR\x05state\x12\x39\n\nupdated_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12G\n\x0f\x61llowed_actions\x18\x07 \x03(\x0b\x32\x1e.deixicpublic.v1.ReceiptActionR\x0e\x61llowedActions\x12>\n\x08\x65vidence\x18\x08 \x03(\x0b\x32\".deixicpublic.v1.EvidenceReferenceR\x08\x65vidence\x12N\n\x11\x63oding_acceptance\x18\t \x01(\x0b\x32!.deixicpublic.v1.CodingAcceptanceR\x10\x63odingAcceptance\"B\n\x0eModelSelection\x12\x1a\n\x08provider\x18\x01 \x01(\tR\x08provider\x12\x14\n\x05model\x18\x02 \x01(\tR\x05model\"{\n\x0e\x41vailableModel\x12\x1a\n\x08provider\x18\x01 \x01(\tR\x08provider\x12\x14\n\x05model\x18\x02 \x01(\tR\x05model\x12\x14\n\x05ready\x18\x03 \x01(\x08R\x05ready\x12!\n\x0c\x64isplay_name\x18\x04 \x01(\tR\x0b\x64isplayName\"\xd5\x02\n\x0eSetupReadiness\x12\x1e\n\naccessible\x18\x01 \x01(\x08R\naccessible\x12\x31\n\x14missing_requirements\x18\x02 \x03(\tR\x13missingRequirements\x12=\n\tselection\x18\x03 \x01(\x0b\x32\x1f.deixicpublic.v1.ModelSelectionR\tselection\x12\x44\n\rdefault_model\x18\x04 \x01(\x0b\x32\x1f.deixicpublic.v1.AvailableModelR\x0c\x64\x65\x66\x61ultModel\x12J\n\x10\x61vailable_models\x18\x05 \x03(\x0b\x32\x1f.deixicpublic.v1.AvailableModelR\x0f\x61vailableModels\x12\x1f\n\x0bnext_action\x18\x06 \x01(\tR\nnextAction\"\xa9\x01\n\x18GetModelReadinessRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12=\n\tselection\x18\x02 \x01(\x0b\x32\x1f.deixicpublic.v1.ModelSelectionR\tselection\x12 \n\x0b\x65nvironment\x18\x03 \x01(\tR\x0b\x65nvironment\"\xea\x02\n\x19GetModelReadinessResponse\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12=\n\tselection\x18\x02 \x01(\x0b\x32\x1f.deixicpublic.v1.ModelSelectionR\tselection\x12 \n\x0b\x65nvironment\x18\x03 \x01(\tR\x0b\x65nvironment\x12:\n\x05state\x18\x04 \x01(\x0e\x32$.deixicpublic.v1.ModelReadinessStateR\x05state\x12\x43\n\x0cnext_actions\x18\x05 \x03(\x0e\x32 .deixicpublic.v1.ModelNextActionR\x0bnextActions\x12=\n\x0c\x65valuated_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x0b\x65valuatedAt\"\x8f\x01\n\nClientRule\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x14\n\x05title\x18\x02 \x01(\tR\x05title\x12#\n\rbody_markdown\x18\x03 \x01(\tR\x0c\x62odyMarkdown\x12\x36\n\x05scope\x18\x04 \x01(\x0e\x32 .deixicpublic.v1.ClientRuleScopeR\x05scope\"k\n\x0b\x43lientSkill\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x16\n\x06source\x18\x02 \x01(\tR\x06source\x12\x18\n\x07version\x18\x03 \x01(\tR\x07version\x12\x1a\n\x08required\x18\x04 \x01(\x08R\x08required\"d\n\x0f\x43lientMcpServer\x12\x12\n\x04name\x18\x01 \x01(\tR\x04name\x12\x1f\n\x0burl_pattern\x18\x02 \x01(\tR\nurlPattern\x12\x1c\n\ttransport\x18\x03 \x01(\tR\ttransport\"\x81\x01\n\x0f\x43lientMcpPolicy\x12\x32\n\x04mode\x18\x01 \x01(\x0e\x32\x1e.deixicpublic.v1.ClientMcpModeR\x04mode\x12:\n\x07servers\x18\x02 \x03(\x0b\x32 .deixicpublic.v1.ClientMcpServerR\x07servers\"E\n\x15GetClientSetupRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\"\xe6\x02\n\x16GetClientSetupResponse\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x18\n\x07version\x18\x02 \x01(\x04R\x07version\x12\x37\n\tissued_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\x08issuedAt\x12\x31\n\x05rules\x18\x04 \x03(\x0b\x32\x1b.deixicpublic.v1.ClientRuleR\x05rules\x12\x34\n\x06skills\x18\x05 \x03(\x0b\x32\x1c.deixicpublic.v1.ClientSkillR\x06skills\x12\x32\n\x03mcp\x18\x06 \x01(\x0b\x32 .deixicpublic.v1.ClientMcpPolicyR\x03mcp\x12.\n\x13sandbox_policy_toml\x18\x07 \x01(\tR\x11sandboxPolicyToml\"T\n\rIssueEvidence\x12\x12\n\x04kind\x18\x01 \x01(\tR\x04kind\x12\x1b\n\tsource_id\x18\x02 \x01(\tR\x08sourceId\x12\x12\n\x04text\x18\x03 \x01(\tR\x04text\"\x8f\x01\n\x0cIssueContext\x12-\n\x12reproduction_steps\x18\x01 \x01(\tR\x11reproductionSteps\x12\x14\n\x05model\x18\x02 \x01(\tR\x05model\x12:\n\x08\x65vidence\x18\x03 \x03(\x0b\x32\x1e.deixicpublic.v1.IssueEvidenceR\x08\x65vidence\"\xcb\x02\n\x18SubmitIssueReportRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12 \n\x0b\x64\x65scription\x18\x02 \x01(\tR\x0b\x64\x65scription\x12+\n\x11\x65xpected_behavior\x18\x03 \x01(\tR\x10\x65xpectedBehavior\x12\x1f\n\x0b\x61pp_version\x18\x04 \x01(\tR\nappVersion\x12/\n\x13include_diagnostics\x18\x05 \x01(\x08R\x12includeDiagnostics\x12\'\n\x0fidempotency_key\x18\x06 \x01(\tR\x0eidempotencyKey\x12\x37\n\x07\x63ontext\x18\x07 \x01(\x0b\x32\x1d.deixicpublic.v1.IssueContextR\x07\x63ontext\";\n\x0bIssueReport\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x1c\n\treference\x18\x02 \x01(\tR\treference\"Q\n\x19SubmitIssueReportResponse\x12\x34\n\x06report\x18\x01 \x01(\x0b\x32\x1c.deixicpublic.v1.IssueReportR\x06report\"C\n\rBusinessMoney\x12\x16\n\x06\x61mount\x18\x01 \x01(\tR\x06\x61mount\x12\x1a\n\x08\x63urrency\x18\x02 \x01(\tR\x08\x63urrency\"6\n\x17\x42usinessObjectReference\x12\x1b\n\tobject_id\x18\x01 \x01(\tR\x08objectId\"K\n\x19\x42usinessArtifactReference\x12.\n\x13\x61rtifact_version_id\x18\x01 \x01(\tR\x11\x61rtifactVersionId\"*\n\x10\x42usinessTextList\x12\x16\n\x06values\x18\x01 \x03(\tR\x06values\"\x87\x04\n\x12\x42usinessFieldValue\x12\x19\n\x08\x66ield_id\x18\x01 \x01(\tR\x07\x66ieldId\x12\x14\n\x04text\x18\x02 \x01(\tH\x00R\x04text\x12\x1a\n\x07integer\x18\x03 \x01(\x03H\x00R\x07integer\x12\x1a\n\x07\x62oolean\x18\x04 \x01(\x08H\x00R\x07\x62oolean\x12\x1a\n\x07\x64\x65\x63imal\x18\x05 \x01(\tH\x00R\x07\x64\x65\x63imal\x12\x36\n\x05money\x18\x06 \x01(\x0b\x32\x1e.deixicpublic.v1.BusinessMoneyH\x00R\x05money\x12\x1f\n\nenum_value\x18\x07 \x01(\tH\x00R\tenumValue\x12\x14\n\x04\x64\x61te\x18\x08 \x01(\tH\x00R\x04\x64\x61te\x12\x1e\n\ttimestamp\x18\t \x01(\tH\x00R\ttimestamp\x12H\n\treference\x18\n \x01(\x0b\x32(.deixicpublic.v1.BusinessObjectReferenceH\x00R\treference\x12H\n\x08\x61rtifact\x18\x0b \x01(\x0b\x32*.deixicpublic.v1.BusinessArtifactReferenceH\x00R\x08\x61rtifact\x12@\n\ttext_list\x18\x0c \x01(\x0b\x32!.deixicpublic.v1.BusinessTextListH\x00R\x08textListB\x07\n\x05value\"\xac\x02\n\x0e\x42usinessObject\x12\x1b\n\tobject_id\x18\x01 \x01(\tR\x08objectId\x12\x17\n\x07type_id\x18\x02 \x01(\tR\x06typeId\x12\'\n\x0fschema_revision\x18\x03 \x01(\x03R\x0eschemaRevision\x12\x1a\n\x08revision\x18\x04 \x01(\x03R\x08revision\x12;\n\x06values\x18\x05 \x03(\x0b\x32#.deixicpublic.v1.BusinessFieldValueR\x06values\x12\x18\n\x07\x64\x65leted\x18\x06 \x01(\x08R\x07\x64\x65leted\x12\x1d\n\nupdated_at\x18\t \x01(\tR\tupdatedAt\x12\x1d\n\ncreated_at\x18\n \x01(\tR\tcreatedAtJ\x04\x08\x07\x10\x08J\x04\x08\x08\x10\t\"\x91\x02\n\x1b\x43reateBusinessObjectRequest\x12\'\n\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12!\n\x0cworkspace_id\x18\x02 \x01(\tR\x0bworkspaceId\x12\'\n\x0fidempotency_key\x18\x03 \x01(\tR\x0eidempotencyKey\x12\x17\n\x07type_id\x18\x04 \x01(\tR\x06typeId\x12\'\n\x0fschema_revision\x18\x05 \x01(\x03R\x0eschemaRevision\x12;\n\x06values\x18\x06 \x03(\x0b\x32#.deixicpublic.v1.BusinessFieldValueR\x06values\"W\n\x1c\x43reateBusinessObjectResponse\x12\x37\n\x06object\x18\x01 \x01(\x0b\x32\x1f.deixicpublic.v1.BusinessObjectR\x06object\"\x8f\x01\n\x18GetBusinessObjectRequest\x12\'\n\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12!\n\x0cworkspace_id\x18\x02 \x01(\tR\x0bworkspaceId\x12\x1b\n\tobject_id\x18\x04 \x01(\tR\x08objectIdJ\x04\x08\x03\x10\x04J\x04\x08\x05\x10\x06\"T\n\x19GetBusinessObjectResponse\x12\x37\n\x06object\x18\x01 \x01(\x0b\x32\x1f.deixicpublic.v1.BusinessObjectR\x06object\"\xc2\x02\n\x1bUpdateBusinessObjectRequest\x12\'\n\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12!\n\x0cworkspace_id\x18\x02 \x01(\tR\x0bworkspaceId\x12\'\n\x0fidempotency_key\x18\x03 \x01(\tR\x0eidempotencyKey\x12\x1b\n\tobject_id\x18\x04 \x01(\tR\x08objectId\x12+\n\x11\x65xpected_revision\x18\x05 \x01(\x03R\x10\x65xpectedRevision\x12;\n\x06values\x18\x06 \x03(\x0b\x32#.deixicpublic.v1.BusinessFieldValueR\x06values\x12\'\n\x0fschema_revision\x18\x07 \x01(\x03R\x0eschemaRevision\"W\n\x1cUpdateBusinessObjectResponse\x12\x37\n\x06object\x18\x01 \x01(\x0b\x32\x1f.deixicpublic.v1.BusinessObjectR\x06object\"\xdc\x01\n\x1b\x44\x65leteBusinessObjectRequest\x12\'\n\x0forganization_id\x18\x01 \x01(\tR\x0eorganizationId\x12!\n\x0cworkspace_id\x18\x02 \x01(\tR\x0bworkspaceId\x12\'\n\x0fidempotency_key\x18\x03 \x01(\tR\x0eidempotencyKey\x12\x1b\n\tobject_id\x18\x04 \x01(\tR\x08objectId\x12+\n\x11\x65xpected_revision\x18\x05 \x01(\x03R\x10\x65xpectedRevision\"W\n\x1c\x44\x65leteBusinessObjectResponse\x12\x37\n\x06object\x18\x01 \x01(\x0b\x32\x1f.deixicpublic.v1.BusinessObjectR\x06object\"\x92\x01\n\x10GetThreadRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12\x14\n\x05limit\x18\x03 \x01(\x05R\x05limit\x12\x1d\n\npage_token\x18\x04 \x01(\tR\tpageToken\"\xe9\x02\n\x11GetThreadResponse\x12/\n\x06thread\x18\x01 \x01(\x0b\x32\x17.deixicpublic.v1.ThreadR\x06thread\x12\x38\n\x08messages\x18\x02 \x03(\x0b\x32\x1c.deixicpublic.v1.TaskMessageR\x08messages\x12\x34\n\x08receipts\x18\x03 \x03(\x0b\x32\x18.deixicpublic.v1.ReceiptR\x08receipts\x12/\n\x05turns\x18\x04 \x03(\x0b\x32\x19.deixicpublic.v1.TaskTurnR\x05turns\x12#\n\rreplay_cursor\x18\x05 \x01(\x03R\x0creplayCursor\x12&\n\x0fnext_page_token\x18\x06 \x01(\tR\rnextPageToken\x12\x35\n\x05setup\x18\x07 \x01(\x0b\x32\x1f.deixicpublic.v1.SetupReadinessR\x05setup\"^\n\x12ListThreadsRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1a\n\x08\x61rchived\x18\x02 \x01(\x08R\x08\x61rchived\"H\n\x13ListThreadsResponse\x12\x31\n\x07threads\x18\x01 \x03(\x0b\x32\x17.deixicpublic.v1.ThreadR\x07threads\"v\n\x13RenameThreadRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12\x14\n\x05title\x18\x03 \x01(\tR\x05title\"a\n\x14RenameThreadResponse\x12/\n\x06thread\x18\x01 \x01(\x0b\x32\x17.deixicpublic.v1.ThreadR\x06thread\x12\x18\n\x07\x63hanged\x18\x02 \x01(\x08R\x07\x63hanged\"\xa6\x01\n\x14\x41rchiveThreadRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12\x1a\n\x08\x61rchived\x18\x03 \x01(\x08R\x08\x61rchived\x12\'\n\x0fidempotency_key\x18\x04 \x01(\tR\x0eidempotencyKey\"~\n\x15\x41rchiveThreadResponse\x12/\n\x06thread\x18\x01 \x01(\x0b\x32\x17.deixicpublic.v1.ThreadR\x06thread\x12\x18\n\x07\x63hanged\x18\x02 \x01(\x08R\x07\x63hanged\x12\x1a\n\x08replayed\x18\x03 \x01(\x08R\x08replayed\"\x97\x01\n\x11ListEventsRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12!\n\x0c\x61\x66ter_cursor\x18\x03 \x01(\x03R\x0b\x61\x66terCursor\x12\x14\n\x05limit\x18\x04 \x01(\x05R\x05limit\"\xa2\x02\n\x12ListEventsResponse\x12\x32\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x1a.deixicpublic.v1.TaskEventR\x06\x65vents\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\x03R\nnextCursor\x12\x19\n\x08has_more\x18\x03 \x01(\x08R\x07hasMore\x12%\n\x0ereset_required\x18\x04 \x01(\x08R\rresetRequired\x12\x33\n\x08snapshot\x18\x05 \x01(\x0b\x32\x17.deixicpublic.v1.ThreadR\x08snapshot\x12@\n\x0esnapshot_turns\x18\x06 \x03(\x0b\x32\x19.deixicpublic.v1.TaskTurnR\rsnapshotTurns\"\x82\x01\n\x12WatchEventsRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12!\n\x0c\x61\x66ter_cursor\x18\x03 \x01(\x03R\x0b\x61\x66terCursor\"\x88\x02\n\x13WatchEventsResponse\x12\x32\n\x06\x65vents\x18\x01 \x03(\x0b\x32\x1a.deixicpublic.v1.TaskEventR\x06\x65vents\x12\x1f\n\x0bnext_cursor\x18\x02 \x01(\x03R\nnextCursor\x12%\n\x0ereset_required\x18\x03 \x01(\x08R\rresetRequired\x12\x33\n\x08snapshot\x18\x04 \x01(\x0b\x32\x17.deixicpublic.v1.ThreadR\x08snapshot\x12@\n\x0esnapshot_turns\x18\x05 \x03(\x0b\x32\x19.deixicpublic.v1.TaskTurnR\rsnapshotTurns\"\x9b\x03\n\x0e\x43odingContract\x12#\n\rrepository_id\x18\x01 \x01(\tR\x0crepositoryId\x12\x1e\n\ngeneration\x18\x02 \x01(\x04R\ngeneration\x12\x34\n\x16required_assertion_ids\x18\x03 \x03(\tR\x14requiredAssertionIds\x12%\n\x0erequire_review\x18\x04 \x01(\x08R\rrequireReview\x12)\n\x10require_behavior\x18\x05 \x01(\x08R\x0frequireBehavior\x12\x35\n\x16readiness_requirements\x18\x06 \x03(\tR\x15readinessRequirements\x12)\n\x10\x61uthorized_skips\x18\x07 \x03(\tR\x0f\x61uthorizedSkips\x12\x37\n\x17\x61uthorized_dispositions\x18\x08 \x03(\tR\x16\x61uthorizedDispositions\x12!\n\x0coutput_paths\x18\t \x03(\tR\x0boutputPaths\"\xbf\x03\n\x11SubmitTaskRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12\x12\n\x04\x62ody\x18\x03 \x01(\tR\x04\x62ody\x12\'\n\x0fidempotency_key\x18\x04 \x01(\tR\x0eidempotencyKey\x12\x30\n\x14\x63ontinuation_task_id\x18\x05 \x01(\tR\x12\x63ontinuationTaskId\x12,\n\x12reference_task_ids\x18\x06 \x03(\tR\x10referenceTaskIds\x12H\n\x0fmodel_selection\x18\x07 \x01(\x0b\x32\x1f.deixicpublic.v1.ModelSelectionR\x0emodelSelection\x12H\n\x0f\x63oding_contract\x18\x08 \x01(\x0b\x32\x1f.deixicpublic.v1.CodingContractR\x0e\x63odingContract\x12.\n\x13project_resource_id\x18\t \x01(\tR\x11projectResourceId\"\xe7\x01\n\x12SubmitTaskResponse\x12\x36\n\x07message\x18\x01 \x01(\x0b\x32\x1c.deixicpublic.v1.TaskMessageR\x07message\x12>\n\raccepted_turn\x18\x02 \x01(\x0b\x32\x19.deixicpublic.v1.TaskTurnR\x0c\x61\x63\x63\x65ptedTurn\x12#\n\rreplay_cursor\x18\x03 \x01(\x03R\x0creplayCursor\x12\x34\n\x08receipts\x18\x04 \x03(\x0b\x32\x18.deixicpublic.v1.ReceiptR\x08receipts\"\xbb\x01\n\x14InterruptTaskRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12\x17\n\x07turn_id\x18\x03 \x01(\tR\x06turnId\x12\'\n\x0fidempotency_key\x18\x04 \x01(\tR\x0eidempotencyKey\x12\x16\n\x06reason\x18\x05 \x01(\tR\x06reason\"\xa2\x01\n\x15InterruptTaskResponse\x12\x17\n\x07turn_id\x18\x01 \x01(\tR\x06turnId\x12\x1a\n\x08replayed\x18\x02 \x01(\x08R\x08replayed\x12/\n\x05turns\x18\x03 \x03(\x0b\x32\x19.deixicpublic.v1.TaskTurnR\x05turns\x12#\n\rreplay_cursor\x18\x04 \x01(\x03R\x0creplayCursor\"\x87\x03\n\x17RespondToRequestRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1b\n\tthread_id\x18\x02 \x01(\tR\x08threadId\x12\x17\n\x07turn_id\x18\x03 \x01(\tR\x06turnId\x12\x1d\n\nrequest_id\x18\x04 \x01(\tR\trequestId\x12\x17\n\x07\x63\x61ll_id\x18\x05 \x01(\tR\x06\x63\x61llId\x12?\n\x0crequest_kind\x18\x06 \x01(\x0e\x32\x1c.deixicpublic.v1.RequestKindR\x0brequestKind\x12\x37\n\x06\x61\x63tion\x18\x07 \x01(\x0e\x32\x1f.deixicpublic.v1.ResponseActionR\x06\x61\x63tion\x12\x12\n\x04text\x18\x08 \x01(\tR\x04text\x12\x19\n\x08is_error\x18\t \x01(\x08R\x07isError\x12\'\n\x0fidempotency_key\x18\n \x01(\tR\x0eidempotencyKey\"\x8c\x01\n\x18RespondToRequestResponse\x12\x1a\n\x08replayed\x18\x01 \x01(\x08R\x08replayed\x12/\n\x05turns\x18\x02 \x03(\x0b\x32\x19.deixicpublic.v1.TaskTurnR\x05turns\x12#\n\rreplay_cursor\x18\x03 \x01(\x03R\x0creplayCursor\"\xc0\x01\n\x11GetReceiptRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1d\n\nreceipt_id\x18\x02 \x01(\tR\treceiptId\x12\x1b\n\tthread_id\x18\x03 \x01(\tR\x08threadId\x12\x41\n\x1dinclude_coding_output_content\x18\x04 \x01(\x08R\x1aincludeCodingOutputContent\"H\n\x12GetReceiptResponse\x12\x32\n\x07receipt\x18\x01 \x01(\x0b\x32\x18.deixicpublic.v1.ReceiptR\x07receipt\"\xb0\x01\n\x1bResolveReceiptActionRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x1d\n\nreceipt_id\x18\x02 \x01(\tR\treceiptId\x12\x1b\n\taction_id\x18\x03 \x01(\tR\x08\x61\x63tionId\x12\'\n\x0fidempotency_key\x18\x04 \x01(\tR\x0eidempotencyKey\"R\n\x1cResolveReceiptActionResponse\x12\x32\n\x07receipt\x18\x01 \x01(\x0b\x32\x18.deixicpublic.v1.ReceiptR\x07receipt\"\xa4\x01\n\x0eVoiceSelection\x12.\n\x04mode\x18\x01 \x01(\x0e\x32\x1a.deixicpublic.v1.VoiceModeR\x04mode\x12\x1b\n\tvoice_ids\x18\x02 \x03(\tR\x08voiceIds\x12\x45\n\x10tone_adjustments\x18\x03 \x03(\x0e\x32\x1a.deixicpublic.v1.VoiceToneR\x0ftoneAdjustments\"\x9b\x01\n\x17SubmitVoicedTaskRequest\x12\x36\n\x04task\x18\x01 \x01(\x0b\x32\".deixicpublic.v1.SubmitTaskRequestR\x04task\x12H\n\x0fvoice_selection\x18\x02 \x01(\x0b\x32\x1f.deixicpublic.v1.VoiceSelectionR\x0evoiceSelection\"W\n\x18SubmitVoicedTaskResponse\x12;\n\x06result\x18\x01 \x01(\x0b\x32#.deixicpublic.v1.SubmitTaskResponseR\x06result\"F\n\x16GetVoiceCatalogRequest\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\"w\n\nBrandVoice\x12\x19\n\x08voice_id\x18\x01 \x01(\tR\x07voiceId\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12 \n\x0b\x64\x65scription\x18\x03 \x01(\tR\x0b\x64\x65scription\x12\x18\n\x07version\x18\x04 \x01(\x04R\x07version\"\xc0\x01\n\x17GetVoiceCatalogResponse\x12,\n\x05scope\x18\x01 \x01(\x0b\x32\x16.deixicpublic.v1.ScopeR\x05scope\x12\x18\n\x07\x65nabled\x18\x02 \x01(\x08R\x07\x65nabled\x12(\n\x10\x64\x65\x66\x61ult_voice_id\x18\x03 \x01(\tR\x0e\x64\x65\x66\x61ultVoiceId\x12\x33\n\x06voices\x18\x04 \x03(\x0b\x32\x1b.deixicpublic.v1.BrandVoiceR\x06voices*\xd7\x01\n\tTurnState\x12\x1a\n\x16TURN_STATE_UNSPECIFIED\x10\x00\x12\x17\n\x13TURN_STATE_ACCEPTED\x10\x01\x12\x16\n\x12TURN_STATE_RUNNING\x10\x02\x12\x16\n\x12TURN_STATE_WAITING\x10\x03\x12\x18\n\x14TURN_STATE_RESPONDED\x10\x04\x12\x18\n\x14TURN_STATE_COMPLETED\x10\x05\x12\x15\n\x11TURN_STATE_FAILED\x10\x06\x12\x1a\n\x16TURN_STATE_INTERRUPTED\x10\x07*\xae\x01\n\rWaitingReason\x12\x1e\n\x1aWAITING_REASON_UNSPECIFIED\x10\x00\x12\x1b\n\x17WAITING_REASON_APPROVAL\x10\x01\x12\x1d\n\x19WAITING_REASON_USER_INPUT\x10\x02\x12\x1e\n\x1aWAITING_REASON_CLIENT_TOOL\x10\x03\x12!\n\x1dWAITING_REASON_EXTERNAL_RETRY\x10\x04*w\n\x0bMessageRole\x12\x1c\n\x18MESSAGE_ROLE_UNSPECIFIED\x10\x00\x12\x15\n\x11MESSAGE_ROLE_USER\x10\x01\x12\x1a\n\x16MESSAGE_ROLE_ASSISTANT\x10\x02\x12\x17\n\x13MESSAGE_ROLE_SYSTEM\x10\x03*\x9a\x04\n\tEventKind\x12\x1a\n\x16\x45VENT_KIND_UNSPECIFIED\x10\x00\x12\x1c\n\x18\x45VENT_KIND_TURN_ACCEPTED\x10\x01\x12\x1b\n\x17\x45VENT_KIND_TURN_STARTED\x10\x02\x12\x17\n\x13\x45VENT_KIND_PROGRESS\x10\x03\x12 \n\x1c\x45VENT_KIND_APPROVAL_REQUIRED\x10\x04\x12\x1d\n\x19\x45VENT_KIND_INPUT_REQUIRED\x10\x05\x12 \n\x1c\x45VENT_KIND_ARTIFACT_RECORDED\x10\x06\x12\x1d\n\x19\x45VENT_KIND_TURN_COMPLETED\x10\x07\x12\x1a\n\x16\x45VENT_KIND_TURN_FAILED\x10\x08\x12\x1f\n\x1b\x45VENT_KIND_TURN_INTERRUPTED\x10\t\x12#\n\x1f\x45VENT_KIND_CLIENT_TOOL_REQUIRED\x10\n\x12&\n\"EVENT_KIND_EXTERNAL_RETRY_REQUIRED\x10\x0b\x12#\n\x1f\x45VENT_KIND_ASSISTANT_TEXT_DELTA\x10\x0c\x12&\n\"EVENT_KIND_ASSISTANT_TEXT_OBSERVED\x10\r\x12&\n\"EVENT_KIND_MODEL_ATTEMPT_ABANDONED\x10\x0e\x12\x1c\n\x18\x45VENT_KIND_TOOL_PROPOSED\x10\x0f*\xa2\x01\n\x0bRequestKind\x12\x1c\n\x18REQUEST_KIND_UNSPECIFIED\x10\x00\x12\x19\n\x15REQUEST_KIND_APPROVAL\x10\x01\x12\x1b\n\x17REQUEST_KIND_USER_INPUT\x10\x02\x12\x1c\n\x18REQUEST_KIND_CLIENT_TOOL\x10\x03\x12\x1f\n\x1bREQUEST_KIND_EXTERNAL_RETRY\x10\x04*\xa0\x03\n\x0cReceiptState\x12\x1d\n\x19RECEIPT_STATE_UNSPECIFIED\x10\x00\x12\x19\n\x15RECEIPT_STATE_UNKNOWN\x10\x01\x12\x1a\n\x16RECEIPT_STATE_PROPOSED\x10\x02\x12\x18\n\x14RECEIPT_STATE_QUEUED\x10\x03\x12\"\n\x1eRECEIPT_STATE_WAITING_APPROVAL\x10\x04\x12\x19\n\x15RECEIPT_STATE_BLOCKED\x10\x05\x12\x1d\n\x19RECEIPT_STATE_NEEDS_INPUT\x10\x06\x12\x1d\n\x19RECEIPT_STATE_UNAVAILABLE\x10\x07\x12\x19\n\x15RECEIPT_STATE_RUNNING\x10\x08\x12\x1b\n\x17RECEIPT_STATE_SUCCEEDED\x10\t\x12\x1a\n\x16RECEIPT_STATE_VERIFIED\x10\n\x12\x18\n\x14RECEIPT_STATE_DENIED\x10\x0b\x12\x1b\n\x17RECEIPT_STATE_CANCELLED\x10\x0c\x12\x18\n\x14RECEIPT_STATE_FAILED\x10\r*\xc0\x02\n\x13ModelReadinessState\x12%\n!MODEL_READINESS_STATE_UNSPECIFIED\x10\x00\x12\x1f\n\x1bMODEL_READINESS_STATE_READY\x10\x01\x12-\n)MODEL_READINESS_STATE_ACTIVATION_REQUIRED\x10\x02\x12*\n&MODEL_READINESS_STATE_FUNDING_REQUIRED\x10\x03\x12\'\n#MODEL_READINESS_STATE_LIMIT_REACHED\x10\x04\x12*\n&MODEL_READINESS_STATE_ACCESS_SUSPENDED\x10\x05\x12\x31\n-MODEL_READINESS_STATE_TEMPORARILY_UNAVAILABLE\x10\x06*\xa2\x01\n\x0fModelNextAction\x12!\n\x1dMODEL_NEXT_ACTION_UNSPECIFIED\x10\x00\x12+\n\'MODEL_NEXT_ACTION_CONTACT_ADMINISTRATOR\x10\x01\x12\"\n\x1eMODEL_NEXT_ACTION_VIEW_FUNDING\x10\x02\x12\x1b\n\x17MODEL_NEXT_ACTION_RETRY\x10\x03*y\n\x0f\x43lientRuleScope\x12!\n\x1d\x43LIENT_RULE_SCOPE_UNSPECIFIED\x10\x00\x12\"\n\x1e\x43LIENT_RULE_SCOPE_ORGANIZATION\x10\x01\x12\x1f\n\x1b\x43LIENT_RULE_SCOPE_WORKSPACE\x10\x02*\x87\x01\n\rClientMcpMode\x12\x1f\n\x1b\x43LIENT_MCP_MODE_UNSPECIFIED\x10\x00\x12\x18\n\x14\x43LIENT_MCP_MODE_OPEN\x10\x01\x12\x1d\n\x19\x43LIENT_MCP_MODE_ALLOWLIST\x10\x02\x12\x1c\n\x18\x43LIENT_MCP_MODE_DENYLIST\x10\x03*\xd4\x01\n\x0eResponseAction\x12\x1f\n\x1bRESPONSE_ACTION_UNSPECIFIED\x10\x00\x12\x1b\n\x17RESPONSE_ACTION_APPROVE\x10\x01\x12\x18\n\x14RESPONSE_ACTION_DENY\x10\x02\x12\x1a\n\x16RESPONSE_ACTION_ANSWER\x10\x03\x12\x19\n\x15RESPONSE_ACTION_RETRY\x10\x04\x12\x18\n\x14RESPONSE_ACTION_SKIP\x10\x05\x12\x19\n\x15RESPONSE_ACTION_ABORT\x10\x06*}\n\tVoiceMode\x12\x1a\n\x16VOICE_MODE_UNSPECIFIED\x10\x00\x12 \n\x1cVOICE_MODE_WORKSPACE_DEFAULT\x10\x01\x12\x1a\n\x16VOICE_MODE_BRAND_VOICE\x10\x02\x12\x16\n\x12VOICE_MODE_NEUTRAL\x10\x03*m\n\tVoiceTone\x12\x1a\n\x16VOICE_TONE_UNSPECIFIED\x10\x00\x12\x16\n\x12VOICE_TONE_CONCISE\x10\x01\x12\x15\n\x11VOICE_TONE_FORMAL\x10\x02\x12\x15\n\x11VOICE_TONE_WARMER\x10\x03\x32\xf4\x0f\n\x13\x44\x65ixicPublicService\x12R\n\tGetThread\x12!.deixicpublic.v1.GetThreadRequest\x1a\".deixicpublic.v1.GetThreadResponse\x12X\n\x0bListThreads\x12#.deixicpublic.v1.ListThreadsRequest\x1a$.deixicpublic.v1.ListThreadsResponse\x12[\n\x0cRenameThread\x12$.deixicpublic.v1.RenameThreadRequest\x1a%.deixicpublic.v1.RenameThreadResponse\x12^\n\rArchiveThread\x12%.deixicpublic.v1.ArchiveThreadRequest\x1a&.deixicpublic.v1.ArchiveThreadResponse\x12U\n\nListEvents\x12\".deixicpublic.v1.ListEventsRequest\x1a#.deixicpublic.v1.ListEventsResponse\x12Z\n\x0bWatchEvents\x12#.deixicpublic.v1.WatchEventsRequest\x1a$.deixicpublic.v1.WatchEventsResponse0\x01\x12U\n\nSubmitTask\x12\".deixicpublic.v1.SubmitTaskRequest\x1a#.deixicpublic.v1.SubmitTaskResponse\x12g\n\x10SubmitVoicedTask\x12(.deixicpublic.v1.SubmitVoicedTaskRequest\x1a).deixicpublic.v1.SubmitVoicedTaskResponse\x12\x64\n\x0fGetVoiceCatalog\x12\'.deixicpublic.v1.GetVoiceCatalogRequest\x1a(.deixicpublic.v1.GetVoiceCatalogResponse\x12^\n\rInterruptTask\x12%.deixicpublic.v1.InterruptTaskRequest\x1a&.deixicpublic.v1.InterruptTaskResponse\x12g\n\x10RespondToRequest\x12(.deixicpublic.v1.RespondToRequestRequest\x1a).deixicpublic.v1.RespondToRequestResponse\x12U\n\nGetReceipt\x12\".deixicpublic.v1.GetReceiptRequest\x1a#.deixicpublic.v1.GetReceiptResponse\x12s\n\x14ResolveReceiptAction\x12,.deixicpublic.v1.ResolveReceiptActionRequest\x1a-.deixicpublic.v1.ResolveReceiptActionResponse\x12j\n\x11GetModelReadiness\x12).deixicpublic.v1.GetModelReadinessRequest\x1a*.deixicpublic.v1.GetModelReadinessResponse\x12\x61\n\x0eGetClientSetup\x12&.deixicpublic.v1.GetClientSetupRequest\x1a\'.deixicpublic.v1.GetClientSetupResponse\x12j\n\x11SubmitIssueReport\x12).deixicpublic.v1.SubmitIssueReportRequest\x1a*.deixicpublic.v1.SubmitIssueReportResponse\x12s\n\x14\x43reateBusinessObject\x12,.deixicpublic.v1.CreateBusinessObjectRequest\x1a-.deixicpublic.v1.CreateBusinessObjectResponse\x12j\n\x11GetBusinessObject\x12).deixicpublic.v1.GetBusinessObjectRequest\x1a*.deixicpublic.v1.GetBusinessObjectResponse\x12s\n\x14UpdateBusinessObject\x12,.deixicpublic.v1.UpdateBusinessObjectRequest\x1a-.deixicpublic.v1.UpdateBusinessObjectResponse\x12s\n\x14\x44\x65leteBusinessObject\x12,.deixicpublic.v1.DeleteBusinessObjectRequest\x1a-.deixicpublic.v1.DeleteBusinessObjectResponseB=Z;github.com/dx-corp/deixic-go/deixicpublic/v1;deixicpublicv1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -33,28 +33,32 @@ if not _descriptor._USE_C_DESCRIPTORS: _globals['DESCRIPTOR']._loaded_options = None _globals['DESCRIPTOR']._serialized_options = b'Z;github.com/dx-corp/deixic-go/deixicpublic/v1;deixicpublicv1' - _globals['_TURNSTATE']._serialized_start=12637 - _globals['_TURNSTATE']._serialized_end=12852 - _globals['_WAITINGREASON']._serialized_start=12855 - _globals['_WAITINGREASON']._serialized_end=13029 - _globals['_MESSAGEROLE']._serialized_start=13031 - _globals['_MESSAGEROLE']._serialized_end=13150 - _globals['_EVENTKIND']._serialized_start=13153 - _globals['_EVENTKIND']._serialized_end=13691 - _globals['_REQUESTKIND']._serialized_start=13694 - _globals['_REQUESTKIND']._serialized_end=13856 - _globals['_RECEIPTSTATE']._serialized_start=13859 - _globals['_RECEIPTSTATE']._serialized_end=14275 - _globals['_MODELREADINESSSTATE']._serialized_start=14278 - _globals['_MODELREADINESSSTATE']._serialized_end=14598 - _globals['_MODELNEXTACTION']._serialized_start=14601 - _globals['_MODELNEXTACTION']._serialized_end=14763 - _globals['_CLIENTRULESCOPE']._serialized_start=14765 - _globals['_CLIENTRULESCOPE']._serialized_end=14886 - _globals['_CLIENTMCPMODE']._serialized_start=14889 - _globals['_CLIENTMCPMODE']._serialized_end=15024 - _globals['_RESPONSEACTION']._serialized_start=15027 - _globals['_RESPONSEACTION']._serialized_end=15239 + _globals['_TURNSTATE']._serialized_start=13439 + _globals['_TURNSTATE']._serialized_end=13654 + _globals['_WAITINGREASON']._serialized_start=13657 + _globals['_WAITINGREASON']._serialized_end=13831 + _globals['_MESSAGEROLE']._serialized_start=13833 + _globals['_MESSAGEROLE']._serialized_end=13952 + _globals['_EVENTKIND']._serialized_start=13955 + _globals['_EVENTKIND']._serialized_end=14493 + _globals['_REQUESTKIND']._serialized_start=14496 + _globals['_REQUESTKIND']._serialized_end=14658 + _globals['_RECEIPTSTATE']._serialized_start=14661 + _globals['_RECEIPTSTATE']._serialized_end=15077 + _globals['_MODELREADINESSSTATE']._serialized_start=15080 + _globals['_MODELREADINESSSTATE']._serialized_end=15400 + _globals['_MODELNEXTACTION']._serialized_start=15403 + _globals['_MODELNEXTACTION']._serialized_end=15565 + _globals['_CLIENTRULESCOPE']._serialized_start=15567 + _globals['_CLIENTRULESCOPE']._serialized_end=15688 + _globals['_CLIENTMCPMODE']._serialized_start=15691 + _globals['_CLIENTMCPMODE']._serialized_end=15826 + _globals['_RESPONSEACTION']._serialized_start=15829 + _globals['_RESPONSEACTION']._serialized_end=16041 + _globals['_VOICEMODE']._serialized_start=16043 + _globals['_VOICEMODE']._serialized_end=16168 + _globals['_VOICETONE']._serialized_start=16170 + _globals['_VOICETONE']._serialized_end=16279 _globals['_SCOPE']._serialized_start=79 _globals['_SCOPE']._serialized_end=162 _globals['_ERRORDETAIL']._serialized_start=164 @@ -183,6 +187,18 @@ _globals['_RESOLVERECEIPTACTIONREQUEST']._serialized_end=12550 _globals['_RESOLVERECEIPTACTIONRESPONSE']._serialized_start=12552 _globals['_RESOLVERECEIPTACTIONRESPONSE']._serialized_end=12634 - _globals['_DEIXICPUBLICSERVICE']._serialized_start=15242 - _globals['_DEIXICPUBLICSERVICE']._serialized_end=17071 + _globals['_VOICESELECTION']._serialized_start=12637 + _globals['_VOICESELECTION']._serialized_end=12801 + _globals['_SUBMITVOICEDTASKREQUEST']._serialized_start=12804 + _globals['_SUBMITVOICEDTASKREQUEST']._serialized_end=12959 + _globals['_SUBMITVOICEDTASKRESPONSE']._serialized_start=12961 + _globals['_SUBMITVOICEDTASKRESPONSE']._serialized_end=13048 + _globals['_GETVOICECATALOGREQUEST']._serialized_start=13050 + _globals['_GETVOICECATALOGREQUEST']._serialized_end=13120 + _globals['_BRANDVOICE']._serialized_start=13122 + _globals['_BRANDVOICE']._serialized_end=13241 + _globals['_GETVOICECATALOGRESPONSE']._serialized_start=13244 + _globals['_GETVOICECATALOGRESPONSE']._serialized_end=13436 + _globals['_DEIXICPUBLICSERVICE']._serialized_start=16282 + _globals['_DEIXICPUBLICSERVICE']._serialized_end=18318 # @@protoc_insertion_point(module_scope) diff --git a/tests/test_client.py b/tests/test_client.py index af00633..e0bcc47 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -591,3 +591,51 @@ def test_unsupported_offset_fails_before_transport(): with pytest.raises(DeixicError): client.threads.get(channel_id="thread-a", offset=1) assert not transport.requests + + +def test_explicit_blend_is_frozen_before_credentials_and_uses_distinct_rpc(): + selected = public_pb2.VoiceSelection(mode=2, voice_ids=["lead", "support"], tone_adjustments=[3, 1]) + class MutatingCredentials: + can_refresh = False + def get_credential(self): + selected.voice_ids.reverse() + return Credential(access_token="fixture") + transport = FakeTransport([response(public_pb2.SubmitVoicedTaskResponse(result=public_pb2.SubmitTaskResponse(accepted_turn=public_pb2.TaskTurn(turn_id="voiced", sequence=1))))]) + sdk = Deixic(organization_id="org-a", workspace_id="workspace-a", credential_provider=MutatingCredentials(), transport=transport) + assert sdk.messages.send(channel_id="company", body="draft", idempotency_key="voice-key", voice_selection=selected).accepted_turn.turn_id == "voiced" + request = public_pb2.SubmitVoicedTaskRequest.FromString(transport.requests[0]["body"]) + assert transport.requests[0]["url"].endswith("/SubmitVoicedTask") + assert list(request.voice_selection.voice_ids) == ["lead", "support"] + assert list(request.voice_selection.tone_adjustments) == [1, 3] + assert request.task.idempotency_key == "voice-key" + + +def test_voice_catalog_scope_and_selection_bounds(): + transport = FakeTransport([response(public_pb2.GetVoiceCatalogResponse(scope=public_pb2.Scope(organization_id="other", workspace_id="workspace-a")))]) + sdk = Deixic(organization_id="org-a", workspace_id="workspace-a", api_key="fixture", transport=transport) + with pytest.raises(DeixicError, match="different workspace"): + sdk.voices.list() + for selected in [public_pb2.VoiceSelection(mode=2), public_pb2.VoiceSelection(mode=2, voice_ids=["a", "a"]), public_pb2.VoiceSelection(mode=3, voice_ids=["a"]), public_pb2.VoiceSelection(mode=99)]: + with pytest.raises(DeixicError): + sdk.messages.send(channel_id="company", body="draft", idempotency_key="key", voice_selection=selected) + assert len(transport.requests) == 1 + + +def test_voiced_authentication_replays_identical_bytes_and_old_server_never_falls_back(): + selected = public_pb2.VoiceSelection(mode=2, voice_ids=["lead", "support"]) + class MutatingRefresh(RotatingCredentials): + def refresh_credential(self, current): + selected.voice_ids.reverse() + return super().refresh_credential(current) + transport = FakeTransport([FakeResponse(401, b'{"code":"unauthenticated"}'), response(public_pb2.SubmitVoicedTaskResponse(result=public_pb2.SubmitTaskResponse(accepted_turn=public_pb2.TaskTurn(turn_id="turn", sequence=1))))]) + credentials = MutatingRefresh(Credential(access_token="new", subject="subject-a", organization_id="org-a", workspace_id="workspace-a", scopes=("console:write",))) + sdk = Deixic(organization_id="org-a", workspace_id="workspace-a", credential_provider=credentials, transport=transport) + sdk.messages.send(channel_id="company", body="draft", idempotency_key="key", voice_selection=selected) + assert transport.requests[0]["body"] == transport.requests[1]["body"] + assert all(request["url"].endswith("/SubmitVoicedTask") for request in transport.requests) + old = FakeTransport([FakeResponse(404, b'{"code":"unimplemented"}')]) + sdk = Deixic(organization_id="org-a", workspace_id="workspace-a", api_key="fixture", transport=old) + with pytest.raises(DeixicError): + sdk.messages.send(channel_id="company", body="draft", idempotency_key="key", voice_selection=public_pb2.VoiceSelection(mode=3)) + assert len(old.requests) == 1 + assert old.requests[0]["url"].endswith("/SubmitVoicedTask") diff --git a/tests/test_tasks.py b/tests/test_tasks.py index 6cd230d..8e9b279 100644 --- a/tests/test_tasks.py +++ b/tests/test_tasks.py @@ -642,3 +642,33 @@ def test_invalid_acceptance_stays_unacknowledged_and_requires_explicit_replay(): assert error.value.kind == "protocol" assert task.result().status == "unacknowledged" assert len(transport.requests) == 1 + + +def test_v2_checkpoint_retains_blend_through_loss_restart_and_mutation(): + class LostResponse(FakeTransport): + def send(self, *args, **kwargs): + result = super().send(*args, **kwargs) + if len(self.requests) == 1: + raise ConnectionError("lost response") + return result + transport = LostResponse([response(pb.SubmitVoicedTaskResponse(result=accepted())), response(pb.SubmitVoicedTaskResponse(result=accepted()))]) + selected = pb.VoiceSelection(mode=2, voice_ids=["lead", "support"], tone_adjustments=[3]) + checkpoints = [] + def save(value): + checkpoints.append(json.loads(json.dumps(value))) + value["voiceSelection"]["voiceIds"].reverse() + task = prepared(client(transport), voice_selection=selected, on_checkpoint=save) + selected.voice_ids.reverse() + task.checkpoint()["voiceSelection"]["voiceIds"].reverse() + with pytest.raises(DeixicError): + task.submit() + saved = checkpoints[-1] + resumed = client(transport).tasks.resume(json.loads(json.dumps(saved))) + saved["voiceSelection"]["voiceIds"].reverse() + resumed.replay() + assert resumed.checkpoint()["schema"] == "deixic.task.v2" + assert transport.requests[0]["body"] == transport.requests[1]["body"] + assert list(pb.SubmitVoicedTaskRequest.FromString(transport.requests[1]["body"]).voice_selection.voice_ids) == ["lead", "support"] + for corrupted in [dict(resumed.checkpoint(), schema="deixic.task.v1"), dict(resumed.checkpoint(), voiceSelection={"mode": 2, "voiceIds": ["a", "a"], "toneAdjustments": []})]: + with pytest.raises(DeixicError): + client(transport).tasks.resume(corrupted)