ocai-deepseek 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,60 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ *.so
9
+
10
+ # uv / venv
11
+ .venv/
12
+ uv.lock.bak
13
+
14
+ # Tooling caches
15
+ .pytest_cache/
16
+ .ruff_cache/
17
+ .mypy_cache/
18
+ .import_linter_cache/
19
+ .coverage
20
+ htmlcov/
21
+
22
+ # Docs site build output and page cache (zensical build)
23
+ /site/
24
+ /.cache/
25
+
26
+ # Node (future typescript/)
27
+ node_modules/
28
+ *.tsbuildinfo
29
+
30
+ # Go (future go/)
31
+ /go/bin/
32
+
33
+ # Editors / OS. Shared editor settings ARE committed: the multi-root workspace
34
+ # (ocai.code-workspace) and each folder's .vscode/settings.json + extensions.json
35
+ # give Pylance/Ruff the right interpreter per project. Personal files stay local.
36
+ .idea/
37
+ .vscode/*
38
+ !.vscode/settings.json
39
+ !.vscode/extensions.json
40
+ .DS_Store
41
+
42
+ # Per-user agent settings (never commit personal permissions)
43
+ .claude/settings.local.json
44
+ .codex/config.toml
45
+
46
+ # Platform build and browser-test artifacts
47
+ .nuxt/
48
+ .output/
49
+ platform/test-results/
50
+ platform/playwright-report/
51
+
52
+ # Local environment files: the root .env is the active one, .envs/ holds the
53
+ # per-environment variants (`task env -- <ENV>` copies .envs/.env.<ENV> to .env).
54
+ # Never committed: they hold credentials.
55
+ /.env
56
+ /.envs/
57
+ .local/
58
+
59
+ # Task execution fingerprints
60
+ .task/
@@ -0,0 +1,24 @@
1
+ # Changelog — ocai-deepseek
2
+
3
+ All notable changes to the `ocai-deepseek` distribution. Generated from the change files in
4
+ `.changeset/` by the release workflow (ADR 0010); do not edit released sections by hand.
5
+ ## 0.1.1 (2026-11-11)
6
+
7
+ ### Features
8
+
9
+ #### Declare the independently attributable DeepSeek interface package
10
+
11
+ Declare the independently attributable DeepSeek interface package. (WU-44a, #89)
12
+
13
+ #### Qualify independent DeepSeek unary conversion
14
+
15
+ Share compatible mapping through explicit variant configuration while preserving
16
+ DeepSeek identity, mandatory reasoning replay, honest parameter effects and
17
+ measured usage. Add independently censused request encode/audit and response
18
+ decode edges with recoverable unknown-field evidence. (WU-44b, #91)
19
+
20
+ ### Fixes
21
+
22
+ #### Package metadata points at the real repository and the DeepSeek plugin has an extra
23
+
24
+ Homepage, Source, Documentation and Changelog URLs now point at `github.com/ocarinow/ocai` and the docs site. `ocai[deepseek]` installs the DeepSeek plugin and `ocai[all]` includes it. No runtime behavior changed.
@@ -0,0 +1,46 @@
1
+ Metadata-Version: 2.5
2
+ Name: ocai-deepseek
3
+ Version: 0.1.1
4
+ Summary: DeepSeek interface descriptors for ocai; execution qualification pending.
5
+ Project-URL: Homepage, https://github.com/ocarinow/ocai
6
+ Project-URL: Source, https://github.com/ocarinow/ocai
7
+ Project-URL: Documentation, https://ocarinow.github.io/ocai/
8
+ Project-URL: Changelog, https://github.com/ocarinow/ocai/blob/main/python/packages/ocai-deepseek/CHANGELOG.md
9
+ Author: ocai maintainers
10
+ License-Expression: FSL-1.1-ALv2
11
+ Requires-Python: >=3.13
12
+ Requires-Dist: ocai-openai<0.2,>=0.1
13
+ Requires-Dist: ocai<0.2,>=0.1
14
+ Description-Content-Type: text/markdown
15
+
16
+ # ocai-deepseek
17
+
18
+ DeepSeek's separately attributable Chat Completions interface for ocai.
19
+ This source-available package uses FSL-1.1-ALv2.
20
+
21
+ The catalog publishes independently censused unary request encode, request audit
22
+ and response decode edges. Text, function tools, JSON-object output, reasoning
23
+ replay, native finish state and measured usage are qualified by golden fixtures.
24
+ Unknown native data remains recoverable in registered extension banks.
25
+
26
+ There is no registered serving component or streaming edge yet: public chat
27
+ execution fails before provider I/O. Compatible mapping code and wire DTOs reuse
28
+ ocai-openai, while DeepSeek retains its own identity, profiles and contracts.
29
+
30
+ ```python
31
+ from ocai.convert import Catalog
32
+ from ocai.deepseek import FRAGMENT
33
+
34
+ catalog = Catalog.of(FRAGMENT)
35
+ lock = catalog.lock()
36
+ ```
37
+
38
+ `deepseek/chat_completions@2026-11` names ocai's documented-wire observation
39
+ snapshot dated 2026-11-11. It is neither a vendor version header nor a model
40
+ release. Model facts and exclusions are recorded in `docs/providers/deepseek.md`.
41
+ WU-45 enables public unary execution; WU-46 qualifies streaming.
42
+
43
+ Tool histories require original reasoning text for every assistant turn. Missing
44
+ reasoning and unqualified model-dependent top_p are reported UNSUPPORTED. Media,
45
+ beta strict tools, FIM, prefix completion, JSON-schema output, Responses and
46
+ Anthropic-compatible endpoints are outside this initial surface.
@@ -0,0 +1,31 @@
1
+ # ocai-deepseek
2
+
3
+ DeepSeek's separately attributable Chat Completions interface for ocai.
4
+ This source-available package uses FSL-1.1-ALv2.
5
+
6
+ The catalog publishes independently censused unary request encode, request audit
7
+ and response decode edges. Text, function tools, JSON-object output, reasoning
8
+ replay, native finish state and measured usage are qualified by golden fixtures.
9
+ Unknown native data remains recoverable in registered extension banks.
10
+
11
+ There is no registered serving component or streaming edge yet: public chat
12
+ execution fails before provider I/O. Compatible mapping code and wire DTOs reuse
13
+ ocai-openai, while DeepSeek retains its own identity, profiles and contracts.
14
+
15
+ ```python
16
+ from ocai.convert import Catalog
17
+ from ocai.deepseek import FRAGMENT
18
+
19
+ catalog = Catalog.of(FRAGMENT)
20
+ lock = catalog.lock()
21
+ ```
22
+
23
+ `deepseek/chat_completions@2026-11` names ocai's documented-wire observation
24
+ snapshot dated 2026-11-11. It is neither a vendor version header nor a model
25
+ release. Model facts and exclusions are recorded in `docs/providers/deepseek.md`.
26
+ WU-45 enables public unary execution; WU-46 qualifies streaming.
27
+
28
+ Tool histories require original reasoning text for every assistant turn. Missing
29
+ reasoning and unqualified model-dependent top_p are reported UNSUPPORTED. Media,
30
+ beta strict tools, FIM, prefix completion, JSON-schema output, Responses and
31
+ Anthropic-compatible endpoints are outside this initial surface.
@@ -0,0 +1,28 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "ocai-deepseek"
7
+ version = "0.1.1"
8
+ description = "DeepSeek interface descriptors for ocai; execution qualification pending."
9
+ readme = "README.md"
10
+ requires-python = ">=3.13"
11
+ license = "FSL-1.1-ALv2"
12
+ authors = [{ name = "ocai maintainers" }]
13
+ dependencies = ["ocai>=0.1,<0.2", "ocai-openai>=0.1,<0.2"]
14
+
15
+ [project.urls]
16
+ Homepage = "https://github.com/ocarinow/ocai"
17
+ Source = "https://github.com/ocarinow/ocai"
18
+ Documentation = "https://ocarinow.github.io/ocai/"
19
+ Changelog = "https://github.com/ocarinow/ocai/blob/main/python/packages/ocai-deepseek/CHANGELOG.md"
20
+
21
+ [project.entry-points."ocai.fragments"]
22
+ deepseek = "ocai.deepseek:FRAGMENT"
23
+
24
+ [tool.hatch.build.targets.wheel]
25
+ packages = ["src/ocai"]
26
+
27
+ [tool.hatch.build]
28
+ dev-mode-dirs = ["src"]
@@ -0,0 +1,5 @@
1
+ """DeepSeek descriptor distribution; imports publish data without enabling execution."""
2
+
3
+ from ocai.deepseek.chat_completions import FRAGMENT
4
+
5
+ __all__ = ["FRAGMENT"]
@@ -0,0 +1,14 @@
1
+ """Independently qualified unary DeepSeek Chat Completions interface; no serveable component yet."""
2
+
3
+ from ocai.convert.catalog import CatalogFragment
4
+ from ocai.deepseek.chat_completions.descriptor import NODES
5
+ from ocai.deepseek.chat_completions.descriptor import ORIGIN
6
+ from ocai.deepseek.chat_completions.descriptor import PROFILES
7
+ from ocai.deepseek.chat_completions.descriptor import TRAITS
8
+ from ocai.deepseek.chat_completions.edges import EDGES
9
+
10
+ __all__ = ["FRAGMENT"]
11
+
12
+ FRAGMENT = CatalogFragment(
13
+ origin=ORIGIN, nodes=NODES, profiles=PROFILES, traits=(TRAITS,), edges=EDGES
14
+ )
@@ -0,0 +1,168 @@
1
+ """DeepSeek unary semantics over the shared, explicitly configured compatible codec."""
2
+
3
+ from copy import deepcopy
4
+ from dataclasses import replace
5
+ from typing import Any
6
+
7
+ from ocai.chat.types import ChatRequest
8
+ from ocai.chat.types import Part
9
+ from ocai.chat.types import PartText
10
+ from ocai.chat.types import PartUnknown
11
+ from ocai.convert.graph import EdgeOutput
12
+ from ocai.core.fidelity import Disposition
13
+ from ocai.core.fidelity import FieldLoss
14
+ from ocai.core.ir import is_json_array
15
+ from ocai.core.ir import is_json_object
16
+ from ocai.deepseek.chat_completions import descriptor
17
+ from ocai.deepseek.chat_completions.evidence import Evidence
18
+ from ocai.deepseek.chat_completions.evidence import fields
19
+ from ocai.deepseek.chat_completions.evidence import response_payload
20
+ from ocai.deepseek.chat_completions.evidence import retain
21
+ from ocai.deepseek.chat_completions.evidence import tool_calls
22
+ from ocai.deepseek.chat_completions.policy import NAMESPACE
23
+ from ocai.deepseek.chat_completions.policy import inspect_request
24
+ from ocai.deepseek.chat_completions.usage import decode_usage
25
+ from ocai.openai.chat_completions.codec import ChatCompletionsCodec
26
+ from ocai.openai.chat_completions.variant import ChatCompletionsVariant
27
+
28
+ VARIANT = ChatCompletionsVariant(
29
+ request_node=descriptor.CHAT_COMPLETIONS_REQUEST,
30
+ response_node=descriptor.CHAT_COMPLETIONS_RESPONSE,
31
+ chunk_node=descriptor.CHAT_COMPLETIONS_CHUNK,
32
+ traits=descriptor.TRAITS,
33
+ path=descriptor.PATH,
34
+ reasoning_field="reasoning_content",
35
+ max_tokens_field="max_tokens",
36
+ knob_ranges=(("temperature", 0.0, 2.0),),
37
+ finish_reasons=(("insufficient_system_resource", "error"), ("aborted", "error")),
38
+ )
39
+ _REQUEST_FIELDS = {
40
+ "model",
41
+ "messages",
42
+ "tools",
43
+ "tool_choice",
44
+ "temperature",
45
+ "top_p",
46
+ "seed",
47
+ "frequency_penalty",
48
+ "presence_penalty",
49
+ "parallel_tool_calls",
50
+ "logprobs",
51
+ "max_completion_tokens",
52
+ "max_tokens",
53
+ "stop",
54
+ "reasoning_effort",
55
+ "response_format",
56
+ "thinking",
57
+ }
58
+
59
+
60
+ def _bank(extensions: dict[str, Any], evidence: Evidence, key: str) -> dict[str, Any]:
61
+ """Collect native extension values without minting unregistered tomorrow-keys."""
62
+ for name, value in extensions.items():
63
+ retain(evidence, name.removeprefix("deepseek."), value)
64
+ evidence.sort(key=lambda record: record["path"])
65
+ return {key: evidence} if evidence else {}
66
+
67
+
68
+ def _notes(losses: list[FieldLoss]) -> tuple[FieldLoss, ...]:
69
+ return tuple(replace(loss, note=loss.note.replace("openai.", "deepseek.")) for loss in losses)
70
+
71
+
72
+ class DeepSeekCodec(ChatCompletionsCodec):
73
+ """Qualify text, tools, JSON-object and reasoning without enabling execution yet."""
74
+
75
+ def __init__(self) -> None:
76
+ """Use DeepSeek coordinates and field lanes, never OpenAI routing identity."""
77
+ super().__init__(VARIANT)
78
+
79
+ def encode_request(self, request: ChatRequest) -> EdgeOutput:
80
+ """Apply semantic findings to the effective shared-codec output before provider I/O."""
81
+ out = super().encode_request(request)
82
+ losses, shifts = list(out.losses), list(out.shifts)
83
+ inspect_request(request, out.value, losses, shifts)
84
+ return EdgeOutput(out.value, _notes(losses), tuple(shifts))
85
+
86
+ def decode_request(self, payload: dict[str, Any]) -> EdgeOutput:
87
+ """Decode compatible request data and retain unknown native fields by source path."""
88
+ evidence: Evidence = []
89
+ raw: Any = payload
90
+ if not is_json_object(raw):
91
+ retain(evidence, "$", raw)
92
+ raw = {}
93
+ safe = fields(raw, _REQUEST_FIELDS, "", evidence)
94
+ thinking = safe.pop("thinking", None)
95
+ messages = safe.get("messages")
96
+ if is_json_array(messages):
97
+ for index, message in enumerate(messages):
98
+ if not is_json_object(message):
99
+ continue # shared tolerant reader retains the malformed entry
100
+ role = message.get("role")
101
+ if not isinstance(role, str):
102
+ retain(evidence, f"messages[{index}].role", role)
103
+ message["role"] = "unknown"
104
+ if "tool_calls" in message:
105
+ message["tool_calls"] = tool_calls(
106
+ message["tool_calls"], f"messages[{index}].tool_calls", evidence
107
+ )
108
+ out = super().decode_request(safe)
109
+ request = out.value
110
+ additional_evidence = bool(evidence)
111
+ request.extensions = _bank(request.extensions, evidence, "deepseek.request_unmapped")
112
+ if "thinking" in raw:
113
+ request.provider_options[NAMESPACE] = {"thinking": deepcopy(thinking)}
114
+ losses = list(out.losses)
115
+ if additional_evidence and not any(loss.path == "unmapped" for loss in losses):
116
+ losses.append(
117
+ FieldLoss(
118
+ "unmapped",
119
+ Disposition.EXTENSIONS,
120
+ note="unknown native request data retained by source path",
121
+ )
122
+ )
123
+ return EdgeOutput(request, _notes(losses), out.shifts)
124
+
125
+ def _decode_request_content(
126
+ self, index: int, wire_msg: dict[str, Any], losses: list[FieldLoss]
127
+ ) -> list[Part]:
128
+ """Keep future native content tags as unknown parts, without inventing media support."""
129
+ content = wire_msg.get("content")
130
+ if not is_json_array(content):
131
+ return super()._decode_request_content(index, wire_msg, losses)
132
+ parts: list[Part] = []
133
+ for position, item in enumerate(content):
134
+ if not is_json_object(item):
135
+ continue # the shared request evidence sweep retains malformed scalar entries
136
+ if item.get("type") == "text" and isinstance(item.get("text"), str):
137
+ parts.append(PartText(text=item["text"]))
138
+ else:
139
+ parts.append(PartUnknown.from_dict(deepcopy(item)))
140
+ losses.append(
141
+ FieldLoss(
142
+ f"messages[{index}].content[{position}]",
143
+ Disposition.EXTENSIONS,
144
+ note="unqualified native content preserved as PartUnknown",
145
+ )
146
+ )
147
+ return parts
148
+
149
+ def decode_response(self, payload: dict[str, Any]) -> EdgeOutput:
150
+ """Preserve reasoning, native identity and disjoint measured usage through total decode."""
151
+ safe, evidence = response_payload(payload)
152
+ native_usage = safe.pop("usage", None)
153
+ out = super().decode_response(safe)
154
+ response = out.value
155
+ losses = list(out.losses)
156
+ response.usage = decode_usage(native_usage, losses)
157
+ response.raw = deepcopy(payload)
158
+ additional_evidence = bool(evidence)
159
+ response.extensions = _bank(response.extensions, evidence, "deepseek.response_unmapped")
160
+ if additional_evidence:
161
+ losses.append(
162
+ FieldLoss(
163
+ "unmapped",
164
+ Disposition.EXTENSIONS,
165
+ note="unknown native response data retained by source path",
166
+ )
167
+ )
168
+ return EdgeOutput(response, _notes(losses), out.shifts)
@@ -0,0 +1,43 @@
1
+ """DeepSeek identity and hosting facts, distinct from conversion qualification."""
2
+
3
+ from datetime import date
4
+
5
+ from ocai.core.identity import CHAT_CHUNK
6
+ from ocai.core.identity import CHAT_REQUEST
7
+ from ocai.core.identity import CHAT_RESPONSE
8
+ from ocai.core.identity import NodeId
9
+ from ocai.core.identity import Origin
10
+ from ocai.core.identity import Status
11
+ from ocai.core.profile import CapabilityProfile
12
+ from ocai.core.profile import Support
13
+ from ocai.core.traits import DialectTraits
14
+
15
+ PROVIDER = "deepseek"
16
+ INTERFACE = "chat_completions"
17
+ # Observation snapshot, not a vendor API version or model release.
18
+ TAG = "2026-11"
19
+ RELEASED = date(2026, 11, 11)
20
+ BASE_URL = "https://api.deepseek.com"
21
+ PATH = "/chat/completions"
22
+ MODEL_IDS = ("deepseek-flash", "deepseek-v4-pro")
23
+ ORIGIN = Origin(distribution="ocai-deepseek", version="0.1.0")
24
+
25
+ CHAT_COMPLETIONS_REQUEST = NodeId(PROVIDER, INTERFACE, TAG, CHAT_REQUEST, RELEASED, Status.STABLE)
26
+ CHAT_COMPLETIONS_RESPONSE = NodeId(PROVIDER, INTERFACE, TAG, CHAT_RESPONSE, RELEASED, Status.STABLE)
27
+ CHAT_COMPLETIONS_CHUNK = NodeId(PROVIDER, INTERFACE, TAG, CHAT_CHUNK, RELEASED, Status.STABLE)
28
+ NODES = (CHAT_COMPLETIONS_REQUEST, CHAT_COMPLETIONS_RESPONSE, CHAT_COMPLETIONS_CHUNK)
29
+ TRAITS = DialectTraits(vendor=PROVIDER, first_party_base_url=BASE_URL)
30
+ # Only independently qualified features are declared; media remains unknown.
31
+ PROFILES = tuple(
32
+ CapabilityProfile(
33
+ provider=PROVIDER,
34
+ interface=INTERFACE,
35
+ model_pattern=model,
36
+ features={
37
+ "chat.config.output.json_schema": Support.ABSENT,
38
+ "chat.config.output.json": Support.NATIVE,
39
+ "chat.parts.reasoning.replay": Support.NATIVE,
40
+ },
41
+ )
42
+ for model in MODEL_IDS
43
+ )
@@ -0,0 +1,221 @@
1
+ """Independently censused DeepSeek unary edges; no serving or stream registration."""
2
+
3
+ from ocai.convert.contract import DeclaredDisposition
4
+ from ocai.convert.contract import EdgeContract
5
+ from ocai.convert.graph import Edge
6
+ from ocai.core.fidelity import Disposition
7
+ from ocai.core.fidelity import SemanticShift
8
+ from ocai.core.identity import CHAT_REQUEST
9
+ from ocai.core.identity import CHAT_RESPONSE
10
+ from ocai.core.identity import canonical_node
11
+ from ocai.deepseek.chat_completions.codec import DeepSeekCodec
12
+ from ocai.deepseek.chat_completions.descriptor import CHAT_COMPLETIONS_REQUEST
13
+ from ocai.deepseek.chat_completions.descriptor import CHAT_COMPLETIONS_RESPONSE
14
+ from ocai.deepseek.chat_completions.descriptor import ORIGIN
15
+
16
+ _CODEC = DeepSeekCodec()
17
+
18
+ ENCODE_REQUEST_CONTRACT = EdgeContract(
19
+ census={
20
+ **{
21
+ f"{path}.{lane}": DeclaredDisposition(Disposition.UNSUPPORTED)
22
+ for path in (
23
+ "config",
24
+ "config.reasoning",
25
+ "config.output",
26
+ "config.audio",
27
+ "config.cache",
28
+ "messages[]",
29
+ "messages[].parts[]",
30
+ "messages[].parts[].parts[]",
31
+ "messages[].parts[].annotations[]",
32
+ "tools[]",
33
+ "tool_choice",
34
+ )
35
+ for lane in ("extensions[]", "provider_options[deepseek.chat_completions]")
36
+ },
37
+ "messages[].role": DeclaredDisposition(Disposition.EXACT),
38
+ "messages[].parts[text]": DeclaredDisposition(Disposition.EXACT),
39
+ "messages[].parts[tool_call]": DeclaredDisposition(Disposition.EXACT),
40
+ "messages[].parts[reasoning]": DeclaredDisposition(
41
+ Disposition.UNSUPPORTED,
42
+ "required history must be present; plain text replay otherwise maps exactly",
43
+ ),
44
+ "messages[].parts[]": DeclaredDisposition(
45
+ Disposition.DROPPED, "media, server tools and unqualified parts have no mapped lane"
46
+ ),
47
+ "config.stop_sequences": DeclaredDisposition(Disposition.RENAMED),
48
+ "messages[].parts[].text": DeclaredDisposition(Disposition.UNSUPPORTED),
49
+ "messages[].parts[].annotations": DeclaredDisposition(Disposition.UNSUPPORTED),
50
+ "messages[].parts[].anchor": DeclaredDisposition(Disposition.UNSUPPORTED),
51
+ "messages[].parts[].signature": DeclaredDisposition(Disposition.UNSUPPORTED),
52
+ "messages[].parts[].opaque": DeclaredDisposition(Disposition.UNSUPPORTED),
53
+ "messages[].parts[].source": DeclaredDisposition(Disposition.UNSUPPORTED),
54
+ "messages[].parts[].annotations[].opaque": DeclaredDisposition(Disposition.UNSUPPORTED),
55
+ "messages[].parts[].is_error": DeclaredDisposition(Disposition.DROPPED),
56
+ "messages[].parts[].parts[]": DeclaredDisposition(Disposition.DROPPED),
57
+ "messages": DeclaredDisposition(Disposition.UNSUPPORTED),
58
+ "tools": DeclaredDisposition(Disposition.EXACT),
59
+ "tools[]": DeclaredDisposition(Disposition.UNSUPPORTED),
60
+ "tool_choice": DeclaredDisposition(Disposition.UNSUPPORTED),
61
+ "anchors[]": DeclaredDisposition(Disposition.UNSUPPORTED),
62
+ "extensions[]": DeclaredDisposition(Disposition.DROPPED),
63
+ "extensions[ocai.request_unparsed_anchors]": DeclaredDisposition(Disposition.UNSUPPORTED),
64
+ "config.temperature": DeclaredDisposition(Disposition.APPROXIMATED),
65
+ "config.top_p": DeclaredDisposition(Disposition.UNSUPPORTED),
66
+ "config.seed": DeclaredDisposition(Disposition.UNSUPPORTED),
67
+ "config.frequency_penalty": DeclaredDisposition(Disposition.EXACT),
68
+ "config.presence_penalty": DeclaredDisposition(Disposition.EXACT),
69
+ "config.parallel_tool_calls": DeclaredDisposition(Disposition.UNSUPPORTED),
70
+ "config.max_output_tokens": DeclaredDisposition(Disposition.APPROXIMATED),
71
+ "config.reasoning.budget_tokens": DeclaredDisposition(Disposition.UNSUPPORTED),
72
+ "config.reasoning.include_thoughts": DeclaredDisposition(Disposition.UNSUPPORTED),
73
+ "messages[].parts[refusal]": DeclaredDisposition(Disposition.UNSUPPORTED),
74
+ "provider_options[deepseek.chat_completions].tools": DeclaredDisposition(
75
+ Disposition.UNSUPPORTED
76
+ ),
77
+ "config.reasoning.effort": DeclaredDisposition(Disposition.UNSUPPORTED),
78
+ "config.output": DeclaredDisposition(Disposition.UNSUPPORTED),
79
+ "config.top_k": DeclaredDisposition(Disposition.UNSUPPORTED),
80
+ "config.logprobs": DeclaredDisposition(Disposition.EXACT),
81
+ "config.modalities": DeclaredDisposition(Disposition.DROPPED),
82
+ "config.audio": DeclaredDisposition(Disposition.DROPPED),
83
+ "config.cache": DeclaredDisposition(Disposition.DROPPED),
84
+ **{
85
+ f"provider_options[deepseek.chat_completions].{key}": DeclaredDisposition(
86
+ Disposition.UNSUPPORTED
87
+ )
88
+ for key in (
89
+ "thinking",
90
+ "reasoning_effort",
91
+ "top_p",
92
+ "seed",
93
+ "parallel_tool_calls",
94
+ "max_completion_tokens",
95
+ "n",
96
+ "tool_choice",
97
+ "response_format",
98
+ )
99
+ },
100
+ "provider_options[deepseek.chat_completions].max_tokens": DeclaredDisposition(
101
+ Disposition.APPROXIMATED
102
+ ),
103
+ (
104
+ "provider_options[deepseek.chat_completions].messages[].reasoning_content"
105
+ ): DeclaredDisposition(Disposition.UNSUPPORTED),
106
+ },
107
+ semantic_shifts=(
108
+ *(
109
+ SemanticShift(
110
+ kind="deepseek.thinking_override",
111
+ path=path,
112
+ note="thinking selector overrides effort",
113
+ )
114
+ for path in (
115
+ "config.reasoning.effort",
116
+ "provider_options[deepseek.chat_completions].reasoning_effort",
117
+ )
118
+ ),
119
+ SemanticShift(
120
+ kind="relocation",
121
+ path="messages[].parts[]",
122
+ note="tool results relocate into sibling tool messages",
123
+ ),
124
+ *(
125
+ SemanticShift(
126
+ kind="deepseek.ignored_parameter",
127
+ path=path,
128
+ note="provider accepts but ignores the supplied parameter",
129
+ )
130
+ for key in ("temperature", "frequency_penalty", "presence_penalty")
131
+ for path in (f"config.{key}", f"provider_options[deepseek.chat_completions].{key}")
132
+ ),
133
+ *(
134
+ SemanticShift(
135
+ kind="deepseek.effort_alias",
136
+ path=path,
137
+ note="provider interprets an effort alias; supplied value stays verbatim",
138
+ )
139
+ for path in (
140
+ "config.reasoning.effort",
141
+ "provider_options[deepseek.chat_completions].reasoning_effort",
142
+ )
143
+ ),
144
+ SemanticShift(
145
+ kind="deepseek.reasoning_ignored",
146
+ path="messages[].parts[reasoning]",
147
+ note="provider ignores reasoning replay without tools",
148
+ ),
149
+ SemanticShift(
150
+ kind="deepseek.reasoning_ignored",
151
+ path="provider_options[deepseek.chat_completions].messages[].reasoning_content",
152
+ note="provider ignores reasoning replay without tools",
153
+ ),
154
+ SemanticShift(
155
+ kind="deepseek.reasoning_concatenated",
156
+ path="messages[].parts[reasoning]",
157
+ note="multiple reasoning parts concatenate into the native text lane",
158
+ ),
159
+ ),
160
+ note="canonical request to independently qualified DeepSeek compatible wire",
161
+ )
162
+ DECODE_REQUEST_CONTRACT = EdgeContract(
163
+ census={
164
+ "model": DeclaredDisposition(Disposition.EXTENSIONS),
165
+ "unmapped": DeclaredDisposition(Disposition.EXTENSIONS),
166
+ "tools[]": DeclaredDisposition(Disposition.EXTENSIONS),
167
+ "tool_choice": DeclaredDisposition(Disposition.EXTENSIONS),
168
+ "response_format": DeclaredDisposition(Disposition.EXTENSIONS),
169
+ "messages[].content[]": DeclaredDisposition(Disposition.EXTENSIONS),
170
+ "n": DeclaredDisposition(Disposition.UNSUPPORTED),
171
+ },
172
+ semantic_shifts=(
173
+ SemanticShift(
174
+ kind="relocation",
175
+ path="messages[]",
176
+ note="native tool message rethreads into a canonical tool turn",
177
+ ),
178
+ ),
179
+ note="DeepSeek request audit with exact native reasoning and unknown evidence",
180
+ )
181
+ DECODE_RESPONSE_CONTRACT = EdgeContract(
182
+ census={
183
+ "choices[0].message.content": DeclaredDisposition(Disposition.EXACT),
184
+ "choices[0].message.reasoning_content": DeclaredDisposition(Disposition.EXACT),
185
+ "choices[0].message.tool_calls[]": DeclaredDisposition(Disposition.EXACT),
186
+ "choices[0].finish_reason": DeclaredDisposition(Disposition.EXACT),
187
+ "choices[0].logprobs": DeclaredDisposition(Disposition.EXTENSIONS),
188
+ "unmapped": DeclaredDisposition(Disposition.EXTENSIONS),
189
+ "usage": DeclaredDisposition(
190
+ Disposition.EXTENSIONS,
191
+ "known disjoint counters map exactly; uncertain measurements remain evidence",
192
+ ),
193
+ "id": DeclaredDisposition(Disposition.EXACT),
194
+ "model": DeclaredDisposition(Disposition.EXACT),
195
+ "created": DeclaredDisposition(Disposition.RENAMED),
196
+ },
197
+ note="DeepSeek response to canonical text, reasoning, tools and measured usage",
198
+ )
199
+ EDGES = (
200
+ Edge(
201
+ canonical_node(CHAT_REQUEST),
202
+ CHAT_COMPLETIONS_REQUEST,
203
+ _CODEC.encode_request,
204
+ ENCODE_REQUEST_CONTRACT,
205
+ ORIGIN,
206
+ ),
207
+ Edge(
208
+ CHAT_COMPLETIONS_REQUEST,
209
+ canonical_node(CHAT_REQUEST),
210
+ _CODEC.decode_request,
211
+ DECODE_REQUEST_CONTRACT,
212
+ ORIGIN,
213
+ ),
214
+ Edge(
215
+ CHAT_COMPLETIONS_RESPONSE,
216
+ canonical_node(CHAT_RESPONSE),
217
+ _CODEC.decode_response,
218
+ DECODE_RESPONSE_CONTRACT,
219
+ ORIGIN,
220
+ ),
221
+ )