Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,12 @@ function ConfigurationFieldControl({ copy, field, id, onChange, value, timezone
);
}
const numeric = field.input_kind === "number";
// Models the shipped executors run: the Codex models of the interactive
// endpoint and the managed host's DeepSeek default, which is the canonical
// `deepseek-flash` id of DeepSeek-V4.1-Flash. Suggestions only: the field
// stays free text so an operator can name any id their endpoint serves.
const modelSuggestions = field.key === "executor_model"
? ["gpt-6-sol", "gpt-6-luna", "gpt-6-astra"] : [];
? ["gpt-6-sol", "gpt-6-luna", "gpt-6-astra", "deepseek-flash", "deepseek-v4-pro"] : [];
return (
<label htmlFor={id}>
<span>{label}</span>
Expand Down
15 changes: 11 additions & 4 deletions docs/architecture/rfcs/harness-selection-dsh-pi-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ Both reuse the same Turn host adapters; neither changes the steward default.

A managed host binding names four things: the host adapter, the provider, the
model, and where the credential comes from. The DSH binding is the DSH Turn host
with provider `deepseek-official`, model `deepseek-v4-flash` (DeepSeek V4.1
Flash) at reasoning effort `high`, an endpoint from the operator environment
with provider `deepseek-official`, model `deepseek-flash` (DeepSeek-V4.1-Flash)
at reasoning effort `high`, an endpoint from the operator environment
(`DEEPSEEK_BASE_URL`) and a credential from the operator environment
(`DEEPSEEK_API_KEY`).

Expand Down Expand Up @@ -161,18 +161,25 @@ the channel Session on the endpoint the machine now selects.

Both managed surfaces resolve their **execution profile** from one owner
(`loopx/control_plane/turn_driver/execution_profile.py`): provider
`deepseek-official`, model `deepseek-v4-flash` (DeepSeek V4.1 Flash) and reasoning
`deepseek-official`, model `deepseek-flash` (DeepSeek-V4.1-Flash) and reasoning
effort `high`, overridable by `LOOPX_TURN_PROVIDER` / `LOOPX_TURN_MODEL` /
`LOOPX_TURN_REASONING_EFFORT` and, at lower precedence, the legacy `DSH_PROVIDER`
/ `DSH_MODEL`. The readback is one line, `execution_profile`, shaped
`deepseek-v4-flash@high` in the shipped case, with the provider prepended only
`deepseek-flash@high` in the shipped case, with the provider prepended only
when it is not the shipped one; it is one line because every plan payload carries
it and the agent-facing output budget is a contract, and whichever values the
line names are the values that run, so an owner-set model appears as itself.
Credentials authenticate the selected profile and never choose it; the one
thing a credential resolves is the shipped *host* default of a bounded Turn
nobody selected, and that resolution carries its own readback source.

**Revision (2026-10-04):** the shipped model default moved from the retired
`deepseek-v4-flash` spelling to the canonical `deepseek-flash` id of the same
DeepSeek-V4.1-Flash generation. The retired spelling is still accepted by the
vendor endpoint and remains available as an explicit `LOOPX_TURN_MODEL` /
`DSH_MODEL` override, so a host that pins it is a configuration change rather
than a code change.

Evidence for this binding, separated by source:

- repository-covered without any provider call: with an operator credential the
Expand Down
13 changes: 9 additions & 4 deletions docs/architecture/rfcs/harness-selection-dsh-pi-v0.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ canonical 完成仍是不同事实;本切片不提供动态派生授权或另
### 托管宿主绑定与真实环境验证(2026-09-15)

一个托管宿主绑定要说明四件事:宿主适配器、provider、模型,以及凭据来自哪里。
DSH 绑定是 DSH Turn 宿主 + provider `deepseek-official` + 模型 `deepseek-v4-flash`
(DeepSeek V4.1 Flash)+ 推理档位 `high`,端点取自运维方环境(`DEEPSEEK_BASE_URL`),
DSH 绑定是 DSH Turn 宿主 + provider `deepseek-official` + 模型 `deepseek-flash`
(DeepSeek-V4.1-Flash)+ 推理档位 `high`,端点取自运维方环境(`DEEPSEEK_BASE_URL`),
凭据取自运维方环境(`DEEPSEEK_API_KEY`)。

LoopX **选择**托管有界 Turn 的默认宿主,而从不由启动时的意外推断
Expand Down Expand Up @@ -123,15 +123,20 @@ LoopX **选择**托管有界 Turn 的默认宿主,而从不由启动时的意

两个托管面从同一个所有者解析**执行档位**
(`loopx/control_plane/turn_driver/execution_profile.py`):provider
`deepseek-official`、模型 `deepseek-v4-flash`(DeepSeek V4.1 Flash)、推理档位
`deepseek-official`、模型 `deepseek-flash`(DeepSeek-V4.1-Flash)、推理档位
`high`,可由 `LOOPX_TURN_PROVIDER` / `LOOPX_TURN_MODEL` /
`LOOPX_TURN_REASONING_EFFORT` 覆盖,更低优先级为历史变量 `DSH_PROVIDER` /
`DSH_MODEL`。回读是一行 `execution_profile`:出货形态为 `deepseek-v4-flash@high`,
`DSH_MODEL`。回读是一行 `execution_profile`:出货形态为 `deepseek-flash@high`,
仅当 provider 不是出货值时前置为 `<provider>/…`。之所以只有一行,是因为每个 plan
载荷都携带它,而面向 agent 的输出预算是一份契约;该行写出什么值,就是实际会跑的值,
因此 owner 自己设定的模型会以自身出现。凭据为选定档位提供认证,从不参与选型;凭据
唯一解析的是"无人显式选择时有界 Turn 的出货宿主默认值",且该解析自带来源回读。

**修订(2026-10-04):** 出货模型默认值由已退役的 `deepseek-v4-flash` 拼写改为同一
DeepSeek-V4.1-Flash 世代的正式 ID `deepseek-flash`。该退役拼写仍被厂商端点接受,
并继续作为显式 `LOOPX_TURN_MODEL` / `DSH_MODEL` 覆盖可用,因此仍固定旧拼写的宿主
属于配置变更,而不是代码变更。

该绑定的证据按来源区分:

- 仓库覆盖、无需任何 provider 调用:配置了运维方凭据时出货默认值是 `dsh`,没有时
Expand Down
11 changes: 6 additions & 5 deletions docs/integrations/deepseek-harness-connector.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ loopx turn run-once \
--host generic-cli \
--execution-mode isolated-headless \
--project "$PWD" \
--host-adapter-command-json '["python3", "-m", "loopx.dsh_goal_mode", "--dsh-home", "/path/to/dsh-home", "--cordis", "/path/to/cordis.yml", "--model", "deepseek-v4-flash"]' \
--host-adapter-command-json '["python3", "-m", "loopx.dsh_goal_mode", "--dsh-home", "/path/to/dsh-home", "--cordis", "/path/to/cordis.yml", "--model", "deepseek-flash"]' \
--validation-command-json '["python3", "/path/to/verify-postcondition.py"]' \
--execute
```
Expand Down Expand Up @@ -159,7 +159,7 @@ loopx turn run-once \
--project "$PWD" \
--dsh-home /path/to/dsh-home \
--dsh-cordis /path/to/cordis.yml \
--dsh-model deepseek-v4-flash \
--dsh-model deepseek-flash \
--validation-command-json '["python3", "/path/to/verify-postcondition.py"]' \
--execute
```
Expand All @@ -183,7 +183,8 @@ credential authenticates it, and `codex-cli` is the default when no credential i
configured, because an unauthenticated managed host would refuse to run.

What runs on that host is a separate resolution. The managed execution profile
defaults to `deepseek-official` / `deepseek-v4-flash` / `high`, overridden by
defaults to `deepseek-official` / `deepseek-flash` / `high`, the canonical
DeepSeek-V4.1-Flash id, overridden by
`LOOPX_TURN_PROVIDER` / `LOOPX_TURN_MODEL` / `LOOPX_TURN_REASONING_EFFORT` and, at
lower precedence, by the legacy `DSH_PROVIDER` / `DSH_MODEL`; an explicit
`--dsh-provider` / `--dsh-model` / `--dsh-reasoning-effort` wins over both. The
Expand Down Expand Up @@ -211,7 +212,7 @@ host id:
"credential_env": "DEEPSEEK_API_KEY",
"endpoint_env": "DEEPSEEK_BASE_URL",
"operator_credential_bound": true,
"execution_profile": "deepseek-v4-flash@high",
"execution_profile": "deepseek-flash@high",
"output_token_budget": {
"schema_version": "dsh_output_token_budget_v0",
"scope": "per_model_request",
Expand All @@ -235,7 +236,7 @@ configured. `available` is `false` only when LoopX can prove the planned host
cannot launch here, and `null` for executors this projection does not probe
rather than an unproven claim. Only the credential variable *name* is reported;
the value is never read back. `execution_profile` is the resolved profile as one
line, `deepseek-v4-flash@high` in the shipped shape, with the provider prepended
line, `deepseek-flash@high` in the shipped shape, with the provider prepended
only when it is not the shipped one -- it is one line because every plan carries
it, and the agent-facing output budget is a contract.

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/operator-model-credential.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ Every entry point publishes the same readback, so a reader never has to infer
the host from the name it resolved: `/api/chat/capabilities` reports the
steward's `executor_endpoint`, its `executor_endpoint_source`
(`machine_configuration`, `explicit_config` or `product_default`), the
`execution_profile` (`deepseek-v4-flash@high` on the shipped managed profile),
`execution_profile` (`deepseek-flash@high` on the shipped managed profile),
`available`, the selection policy and allocation reason, and the bound
Session's `session_mode` and `session_status`. The Session persists its chosen
endpoint, model, effort, policy, pool and source revision, so later configuration
Expand Down
4 changes: 2 additions & 2 deletions docs/reference/protocols/loopx-turn-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,11 @@ then the product default.
| execution profile field | product default | operator override | legacy lower-precedence override |
| --- | --- | --- | --- |
| provider | `deepseek-official` | `LOOPX_TURN_PROVIDER` | `DSH_PROVIDER` |
| model | `deepseek-v4-flash` | `LOOPX_TURN_MODEL` | `DSH_MODEL` |
| model | `deepseek-flash` | `LOOPX_TURN_MODEL` | `DSH_MODEL` |
| reasoning effort | `high` | `LOOPX_TURN_REASONING_EFFORT` | — |

The managed `managed_executor` readback reports the resolved profile as one line,
`<model>@<reasoning_effort>` (the shipped shape is `deepseek-v4-flash@high`).
`<model>@<reasoning_effort>` (the shipped shape is `deepseek-flash@high`).
The provider is prepended as `<provider>/…` only when the resolved provider is
not the shipped one, because dropping it for a deviating provider would make the
line claim a profile the Turn would not use. Whichever values the line names are
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ frontend projection; explicitly choosing status-only still uses that projection.
The manager channel's model and reasoning effort follow its executor. On the
interactive CLI endpoint the defaults are `gpt-6-astra` with `high` reasoning; on
the managed host they are the managed execution profile
(`deepseek-official` / `deepseek-v4-flash` / `high`). The machine's
(`deepseek-official` / `deepseek-flash` / `high`). The machine's
`steward_executor` machine configuration decides the executor, the model and the
effort first; set `LOOPX_MANAGER_MODEL` and `LOOPX_MANAGER_REASONING_EFFORT` on
the Chat service when a machine has no such configuration, and the shipped
Expand All @@ -95,7 +95,7 @@ is unchanged. Capabilities expose the manager defaults, their source, and the
status and revision of the machine document they were read from.

The managed profile reaches the channel as the same one-line readback the
governed Turn publishes (`deepseek-v4-flash@high`), so the channel and the
governed Turn publishes (`deepseek-flash@high`), so the channel and the
bounded Turns it drives cannot report two different managed profiles; the
provider is prepended when it is not the shipped one.

Expand Down
2 changes: 1 addition & 1 deletion examples/loopx-managed-turn-operator-flow-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def main() -> None:
)
if planned.get("available") is not True:
fail(f"a stored credential must make the managed host launchable: {planned}")
if planned.get("execution_profile") != "deepseek-v4-flash@high":
if planned.get("execution_profile") != "deepseek-flash@high":
fail(f"the planned profile must be projected: {planned}")

channel = manager_channel_binding(
Expand Down
6 changes: 3 additions & 3 deletions examples/loopx-steward-channel-binding-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ def _assert_selection_moves_the_channel_to_the_managed_host() -> dict[str, objec
"an explicit endpoint selection must be the only way onto the managed host",
)
_assert(
selected["model"] == "deepseek-v4-flash"
selected["model"] == "deepseek-flash"
and selected["model_source"] == MANAGER_MODEL_SOURCE_MANAGED_PROFILE
and selected["execution_profile"] == "deepseek-v4-flash@high",
and selected["execution_profile"] == "deepseek-flash@high",
"the managed endpoint must run the managed execution profile",
)
_assert(
Expand Down Expand Up @@ -370,7 +370,7 @@ def _assert_the_machine_default_is_first_class() -> dict[str, object]:
_assert(
binding["model"] == "deepseek-v4-flash"
and binding["model_source"] == MANAGER_MODEL_SOURCE_MACHINE_CONFIGURATION
and binding["execution_profile"] == "deepseek-v4-flash@high",
and binding["execution_profile"] == "deepseek-flash@high",
"the model and the effort must follow the machine selection",
)
_assert(
Expand Down
4 changes: 2 additions & 2 deletions examples/loopx-steward-managed-chat-smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,9 @@ def _run_turn(args: argparse.Namespace) -> int:
"the managed host must be reached by selection, not by discovering a credential",
)
_assert(
binding["model"] == "deepseek-v4-flash"
binding["model"] == "deepseek-flash"
and binding["model_source"] == "managed_execution_profile"
and binding["execution_profile"] == "deepseek-v4-flash@high",
and binding["execution_profile"] == "deepseek-flash@high",
"the channel must run the managed execution profile",
)

Expand Down
5 changes: 3 additions & 2 deletions examples/managed-research-team/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ uv pip install --python .venv/bin/python -e packages/loopx-ark-turn
Set `ARK_API_KEY`, `ARK_MODEL_ID` and `ARK_ENVIRONMENT_ID` in the process
environment. DSH reuses the machine operator credential; `DEEPSEEK_API_KEY`
is an explicit environment override. The Ark Environment must already belong to the operator;
this launcher never creates or deletes it. The local model defaults to
`deepseek-v4-flash@high`; select another profile with `--dsh-model`.
this launcher never creates or deletes it. The local model defaults to the
managed profile `deepseek-flash@high` (DeepSeek-V4.1-Flash); select another
profile with `--dsh-model`.

Choose a **new private disposable directory**. Never point this example at an
active Goal or research workspace. The canonical Goal quota governs admission;
Expand Down
5 changes: 4 additions & 1 deletion loopx/control_plane/turn_driver/execution_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
# decision recorded once; the environment can override a field, but nothing is
# discovered and no credential participates in the choice.
MANAGED_PROVIDER_DEFAULT = "deepseek-official"
MANAGED_MODEL_DEFAULT = "deepseek-v4-flash"
# The canonical id of DeepSeek-V4.1-Flash. The retired ``deepseek-v4-flash``
# spelling is still accepted by the vendor endpoint and remains available as an
# explicit override, but no shipped surface may name a retired id by default.
MANAGED_MODEL_DEFAULT = "deepseek-flash"
MANAGED_REASONING_EFFORT_DEFAULT = "high"

PROVIDER_ENV_VAR = "LOOPX_TURN_PROVIDER"
Expand Down
4 changes: 2 additions & 2 deletions loopx/dsh_goal_mode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The `deepseek-harness` host surface (aliases: `deepseek_harness`,
```bash
python -m loopx.dsh_goal_mode \
--cordis /path/to/cordis.yml \
--model deepseek-v4-flash \
--model deepseek-flash \
--provider deepseek-official
```

Expand Down Expand Up @@ -128,7 +128,7 @@ SDK 以 `finish_reason=max-tokens` 结束时,内置 host 会产生不可自动
settings for the real runtime.
- Provider, model and reasoning effort come from the managed execution profile
(`loopx/control_plane/turn_driver/execution_profile.py`): product defaults
`deepseek-official` / `deepseek-v4-flash` / `high`, overridden by
`deepseek-official` / `deepseek-flash` / `high`, overridden by
`LOOPX_TURN_PROVIDER` / `LOOPX_TURN_MODEL` / `LOOPX_TURN_REASONING_EFFORT` and,
at lower precedence, by the legacy `DSH_PROVIDER` / `DSH_MODEL`. An explicit CLI
value wins over both, and the resolved profile reports its own source. A
Expand Down
6 changes: 3 additions & 3 deletions packages/loopx-codex-provider-routing/RUNBOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ flowchart LR
CPA --> A[Codex subscription A]
CPA --> B[Codex subscription B]
CPA -. future expansion .-> C[Codex subscription C<br/>reserved, not configured]
CPA --> Ark[Ark DeepSeek V4 Flash]
CPA --> Ark[Ark DeepSeek V4.1 Flash]
CCS[CC Switch<br/>bootstrap / rollback] -. credentials and profiles .-> CPA
Home -. explicit stale-task migration .-> Swap[AgentSwap<br/>offline sidecar]
Swap -. new native session .-> Quarantine[隔离 target task]
Expand Down Expand Up @@ -205,7 +205,7 @@ flowchart LR
| `fast/codex-b/gpt-5.6-sol` | Prefer B:B → A;不落 Ark | `text, image` | Fast,强制 `priority` |
| [`gpt-5.6-luna`](https://developers.openai.com/codex/models) | Luna;复用同一个 A/B 账号环,只在 Codex A/B 间路由,不异构降级到 Ark | `text, image`;推理档位为 `low` 至 `max`,不声明 `ultra` | Standard;不生成重复 Fast alias |
| `codex-c/gpt-5.6-sol` | 预留;只有第三个订阅真实接入并通过矩阵后才暴露 | 由真实 credential 决定 | 不预声明 |
| `ark/deepseek-v4-flash` | 手动固定到 Ark DeepSeek V4 Flash | `text` | 不支持 |
| `ark/deepseek-v4-flash` | 手动固定到 Ark DeepSeek V4.1 Flash(上游 ID 由 operator 配置决定) | `text` | 不支持 |
| `gpt-5.6-sol` | 隐藏 compatibility alias;处理 App / host 继承裸 model metadata 的旧 task,实际行为与 Auto 一致 | `text, image` | 可选,默认关闭 |

模型 ID 是路由契约,不是上游真实 model slug。显示名可本地化,但 ID 一经上线应保持稳定,
Expand Down Expand Up @@ -465,7 +465,7 @@ openai-compatibility:
models:
- name: "<ARK_DEEPSEEK_V4_FLASH_ENDPOINT_ID>"
alias: "deepseek-v4-flash"
display-name: "Ark DeepSeek V4 Flash"
display-name: "Ark DeepSeek V4.1 Flash"
is-compat: true
input-modalities: [text]
output-modalities: [text]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@
"candidates": [
"ark-text"
],
"display_name": "Ark · DeepSeek V4 Flash",
"display_name": "Ark · DeepSeek V4.1 Flash",
"input_modalities": [
"text"
],
Expand Down
38 changes: 37 additions & 1 deletion packages/loopx-codex-provider-routing/smoke/operator_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from unittest.mock import patch

from loopx_codex_provider_routing.operator import rollback, run, snapshot
from loopx_codex_provider_routing.operator_catalog import AppCatalog
from loopx_codex_provider_routing.operator_catalog import AppCatalog, release_suffix
from loopx_codex_provider_routing.operator_runtime import (
CPAOperator,
sha256,
Expand Down Expand Up @@ -159,6 +159,42 @@ def test_runtime_never_maps_subscription_selectors_to_ark(self):
self.assertNotIn(f'alias: "{alias}"', compatibility)
self.assertIn("disable-cooling: false", config)

def test_ark_rows_follow_the_configured_generation(self):
"""One configured id yields one row, labelled by product generation.

The Ark rows are the only DeepSeek surface that names an upstream
endpoint id, so they must be adopted from the operator's configuration
rather than from a literal here; otherwise moving to a newer generation
-- DeepSeek-V4.1-Flash -- would need a source change.
"""

generation = "deepseek-v4-1-flash-ga-261001"
configured = AppCatalog(
CPAOperator(OperatorSettings({**self.data, "ark_model": generation}))
)
self.assertIn(generation, configured.SELECTORS)
self.assertNotIn(self.data["ark_model"], configured.SELECTORS)
self.assertEqual(
configured.SELECTORS[generation], "Ark · DeepSeek V4.1 Flash (261001)"
)
# The two historical aliases keep resolving, and the ids that need no
# release suffix read as their own id.
self.assertEqual(
configured.SELECTORS["ark/deepseek-v4-flash"], "Ark · DeepSeek V4.1 Flash"
)
self.assertEqual(
configured.SELECTORS["deepseek-v4-flash"],
"Ark · DeepSeek V4.1 Flash (legacy id)",
)
self.assertEqual(release_suffix("deepseek-flash"), "deepseek-flash")

def test_runtime_config_renders_the_same_generation_label(self):
# A row that reads as one generation in the App catalog and another in
# the CPA config would make two surfaces disagree about what runs.
config = self.runtime.runtime_config("fixture-key", management_secret="fixture")
self.assertIn('display-name: "Ark · DeepSeek V4.1 Flash"', config)
self.assertIn('alias: "deepseek-v4-flash"', config)

def test_cooldown_reset_is_scoped_and_not_a_health_claim(self):
self.seed()
entry = {"name": "b.json", "auth_index": "fixture-index", "disabled": False}
Expand Down
Loading
Loading