From d8bc2dd4756480787d18c2e696f3ad9ab22448a1 Mon Sep 17 00:00:00 2001
From: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Date: Sun, 20 Sep 2026 16:46:06 +0800
Subject: [PATCH 1/3] feat(steward): persist guided executor allocation
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
---
apps/presentation/dashboard/src/data/chat.ts | 5 +
.../capability-localization.ts | 12 +-
.../personal-workspace/channel-header.tsx | 30 ++
.../src/features/personal-workspace/i18n.tsx | 24 ++
.../machine-configuration-settings.tsx | 22 +-
.../personal-workspace-contract.test.mjs | 2 +-
.../execution-chip.mjs | 18 ++
.../personal-workspace-browser/fixture.mjs | 25 +-
.../typed-actions.mjs | 7 +-
loopx/capabilities/configuration_ui.py | 23 +-
.../capabilities/steward_executor/__init__.py | 36 +++
.../steward_executor/allocation.py | 183 +++++++++++
.../steward_executor/machine_defaults.py | 93 +++++-
loopx/chat_manager.py | 288 ++++++++++++++++--
loopx/chat_runtime.py | 22 +-
loopx/chat_store.py | 17 ++
.../support_control_chat_endpoint.py | 28 +-
loopx/web/chat/asset-retention.json | 6 +-
loopx/web/chat/assets/index-DqTQqqop.css | 1 -
.../{index-p8UhNVLa.js => index-YyYQIQ2W.js} | 47 +--
loopx/web/chat/index.html | 2 +-
.../test_capability_configuration_ui.py | 10 +-
.../test_steward_executor_machine_defaults.py | 72 +++++
tests/test_chat_machine_configuration_api.py | 4 +-
tests/test_chat_manager_context.py | 75 +++++
tests/test_manager_channel_binding.py | 171 ++++++++++-
26 files changed, 1126 insertions(+), 97 deletions(-)
create mode 100644 loopx/capabilities/steward_executor/allocation.py
delete mode 100644 loopx/web/chat/assets/index-DqTQqqop.css
rename loopx/web/chat/assets/{index-p8UhNVLa.js => index-YyYQIQ2W.js} (55%)
diff --git a/apps/presentation/dashboard/src/data/chat.ts b/apps/presentation/dashboard/src/data/chat.ts
index 03659a0ed0..0672baffb6 100644
--- a/apps/presentation/dashboard/src/data/chat.ts
+++ b/apps/presentation/dashboard/src/data/chat.ts
@@ -114,6 +114,11 @@ export const managerChannelBindingSchema = z.object({
executor_kind: z.string(),
model: z.string(),
model_source: z.string(),
+ selection_policy: z.enum(["preferred", "pinned", "flexible"]).default("preferred"),
+ allocation_reason: z.string().default(""),
+ configured_endpoint: z.string().nullable().optional(),
+ eligible_endpoints: z.array(z.string()).default([]),
+ allocation_configuration_revision: z.string().default(""),
credential_env_var: z.string(),
operator_credential_configured: z.boolean(),
output_token_budget: z.object({
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts b/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts
index 76c17ee505..3dd141f41a 100644
--- a/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts
+++ b/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts
@@ -18,7 +18,7 @@ const capabilityCopy: Record
{t("header.managerAllocation", { + policy: managerSelectionPolicyLabel, + reason: managerAllocationReasonLabel, + })}
+ ) : null} {managerExecutionDefaultReason && managerChannelBinding ? ( {t(managerExecutionDefaultReason, { executor: managerChannelBinding.executor_endpoint })} diff --git a/apps/presentation/dashboard/src/features/personal-workspace/i18n.tsx b/apps/presentation/dashboard/src/features/personal-workspace/i18n.tsx index 188b29c0fa..84306faa0a 100644 --- a/apps/presentation/dashboard/src/features/personal-workspace/i18n.tsx +++ b/apps/presentation/dashboard/src/features/personal-workspace/i18n.tsx @@ -422,6 +422,18 @@ const en = { "header.managerExecutionUnavailableOutputBudget": "Selected {executor} has an invalid per-request output-token limit; set a positive integer and reload.", "header.managerEndpointStewardDefault": "Runs {executor}, the steward channel's shipped default. Select an executor explicitly to move it.", "header.managerOutputTokenBudget": "{tokens} tok/request", + "header.managerAllocation": "Selection: {policy} · {reason}", + "header.managerSelectionPreferred": "preferred", + "header.managerSelectionPinned": "pinned", + "header.managerSelectionFlexible": "flexible pool", + "header.managerAllocationUser": "explicit user choice", + "header.managerAllocationPinned": "pinned by machine configuration", + "header.managerAllocationFallback": "primary unavailable; used an eligible fallback", + "header.managerAllocationUnavailable": "no eligible route is currently available", + "header.managerAllocationPrimary": "primary route is available", + "header.managerAllocationProductDefault": "product default", + "header.managerAllocationService": "service environment override", + "header.managerAllocationConfigured": "configured route", "header.managerOverview": "Overview", "header.managerView": "Manager view", "header.openGoalNavigation": "Open Goal navigation", @@ -1492,6 +1504,18 @@ const zhCN: Record