workspace: preserve worker display names
This commit is contained in:
parent
593d3309d9
commit
88d819591e
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
title: 'Preserve requested Worker display names'
|
title: 'Preserve requested Worker display names'
|
||||||
state: 'inprogress'
|
state: 'done'
|
||||||
created_at: '2026-07-11T08:31:24Z'
|
created_at: '2026-07-11T08:31:24Z'
|
||||||
updated_at: '2026-07-11T08:31:54Z'
|
updated_at: '2026-07-11T08:44:11Z'
|
||||||
assignee: null
|
assignee: null
|
||||||
queued_by: 'yoi ticket'
|
queued_by: 'yoi ticket'
|
||||||
queued_at: '2026-07-11T08:31:54Z'
|
queued_at: '2026-07-11T08:31:54Z'
|
||||||
|
|
|
||||||
|
|
@ -39,4 +39,35 @@ Ticket を `yoi ticket` が queued にしました。
|
||||||
State changed to `inprogress`.
|
State changed to `inprogress`.
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- event: implementation_report author: hare at: 2026-07-11T08:44:11Z -->
|
||||||
|
|
||||||
|
## Implementation report
|
||||||
|
|
||||||
|
Fixed Worker display name preservation.
|
||||||
|
|
||||||
|
- Browser Worker create now records the sanitized UI display name in Backend worker registry instead of immediately syncing the Runtime worker id label.
|
||||||
|
- Runtime Worker create API records `requested_worker_name` as display name when provided.
|
||||||
|
- Later Runtime observation/list sync preserves existing registry display_name and only falls back to Runtime label for never-recorded live Workers.
|
||||||
|
- Added coverage that a Worker created with empty browser display_name uses the default `Coding Worker` label in Workers list/detail while keeping worker id separate.
|
||||||
|
|
||||||
|
Validation:
|
||||||
|
- cargo test -q -p yoi-workspace-server
|
||||||
|
- cd web/workspace && deno task check
|
||||||
|
- cd web/workspace && deno task test
|
||||||
|
- cargo test -q
|
||||||
|
- git diff --check
|
||||||
|
- nix build .#yoi --no-link
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- event: state_changed author: "yoi ticket" at: 2026-07-11T08:44:11Z from: inprogress to: done reason: cli_state field: state -->
|
||||||
|
|
||||||
|
## State changed
|
||||||
|
|
||||||
|
State changed to `done`.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -2674,7 +2674,31 @@ async fn create_workspace_worker(
|
||||||
code: "workspace_worker_create_missing_summary".to_string(),
|
code: "workspace_worker_create_missing_summary".to_string(),
|
||||||
message: "Runtime completed worker creation without returning a Worker summary".to_string(),
|
message: "Runtime completed worker creation without returning a Worker summary".to_string(),
|
||||||
})?;
|
})?;
|
||||||
let worker_record = sync_worker_observation(&api, &worker)?;
|
let worker_record = record_worker_summary(
|
||||||
|
&api,
|
||||||
|
&worker,
|
||||||
|
display_name.as_str(),
|
||||||
|
worker.profile.clone(),
|
||||||
|
WorkerRegistryDisplayNamePolicy::UseProvided,
|
||||||
|
)?;
|
||||||
|
if let Some(working_directory) = worker.working_directory.as_ref() {
|
||||||
|
let management_kind = api
|
||||||
|
.store
|
||||||
|
.get_workdir_registry(
|
||||||
|
&api.config.workspace_id,
|
||||||
|
&working_directory.working_directory_id,
|
||||||
|
)?
|
||||||
|
.map(|existing| existing.management_kind)
|
||||||
|
.unwrap_or_else(|| "runtime_unmanaged".to_string());
|
||||||
|
let workdir_record = workdir_record_from_summary(
|
||||||
|
&api,
|
||||||
|
worker.runtime_id.as_str(),
|
||||||
|
working_directory,
|
||||||
|
management_kind.as_str(),
|
||||||
|
);
|
||||||
|
api.store.upsert_workdir_registry(&workdir_record)?;
|
||||||
|
link_worker_to_workdir(&api, &worker_record, &working_directory.working_directory_id)?;
|
||||||
|
}
|
||||||
if let Some(workdir_id) = selected_working_directory_id.as_deref() {
|
if let Some(workdir_id) = selected_working_directory_id.as_deref() {
|
||||||
if api
|
if api
|
||||||
.store
|
.store
|
||||||
|
|
@ -2864,12 +2888,24 @@ async fn create_runtime_worker(
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|claim| claim.working_directory_id.clone())
|
.map(|claim| claim.working_directory_id.clone())
|
||||||
};
|
};
|
||||||
|
let requested_worker_name = request.requested_worker_name.clone();
|
||||||
let result = api
|
let result = api
|
||||||
.runtime
|
.runtime
|
||||||
.spawn_worker(&runtime_id, request)
|
.spawn_worker(&runtime_id, request)
|
||||||
.map_err(|err| err.into_error())?;
|
.map_err(|err| err.into_error())?;
|
||||||
if let Some(worker) = result.worker.as_ref() {
|
if let Some(worker) = result.worker.as_ref() {
|
||||||
let record = sync_worker_observation(&api, worker)?;
|
let display_name = requested_worker_name
|
||||||
|
.as_deref()
|
||||||
|
.filter(|name| !name.trim().is_empty())
|
||||||
|
.unwrap_or(worker.label.as_str())
|
||||||
|
.to_string();
|
||||||
|
let record = record_worker_summary(
|
||||||
|
&api,
|
||||||
|
worker,
|
||||||
|
display_name.as_str(),
|
||||||
|
worker.profile.clone(),
|
||||||
|
WorkerRegistryDisplayNamePolicy::UseProvided,
|
||||||
|
)?;
|
||||||
if worker.working_directory.is_none() {
|
if worker.working_directory.is_none() {
|
||||||
if let Some(workdir_id) = prepared_workdir_id.as_deref() {
|
if let Some(workdir_id) = prepared_workdir_id.as_deref() {
|
||||||
if api
|
if api
|
||||||
|
|
@ -3892,23 +3928,36 @@ fn next_backend_workdir_id(repository_id: &str) -> String {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
enum WorkerRegistryDisplayNamePolicy {
|
||||||
|
PreserveExisting,
|
||||||
|
UseProvided,
|
||||||
|
}
|
||||||
|
|
||||||
fn record_worker_summary(
|
fn record_worker_summary(
|
||||||
api: &WorkspaceApi,
|
api: &WorkspaceApi,
|
||||||
worker: &WorkerSummary,
|
worker: &WorkerSummary,
|
||||||
display_name: &str,
|
display_name: &str,
|
||||||
profile: Option<String>,
|
profile: Option<String>,
|
||||||
|
display_name_policy: WorkerRegistryDisplayNamePolicy,
|
||||||
) -> ApiResult<WorkerRegistryRecord> {
|
) -> ApiResult<WorkerRegistryRecord> {
|
||||||
let timestamp = now_registry_timestamp();
|
let timestamp = now_registry_timestamp();
|
||||||
let worker_id = backend_worker_id(worker.runtime_id.as_str(), worker.worker_id.as_str());
|
let worker_id = backend_worker_id(worker.runtime_id.as_str(), worker.worker_id.as_str());
|
||||||
let existing = api
|
let existing = api
|
||||||
.store
|
.store
|
||||||
.get_worker_registry(&api.config.workspace_id, worker_id.as_str())?;
|
.get_worker_registry(&api.config.workspace_id, worker_id.as_str())?;
|
||||||
|
let display_name = match (display_name_policy, existing.as_ref()) {
|
||||||
|
(WorkerRegistryDisplayNamePolicy::PreserveExisting, Some(record)) => {
|
||||||
|
record.display_name.clone()
|
||||||
|
}
|
||||||
|
_ => display_name.to_string(),
|
||||||
|
};
|
||||||
let record = WorkerRegistryRecord {
|
let record = WorkerRegistryRecord {
|
||||||
workspace_id: api.config.workspace_id.clone(),
|
workspace_id: api.config.workspace_id.clone(),
|
||||||
worker_id: worker_id.clone(),
|
worker_id: worker_id.clone(),
|
||||||
runtime_id: worker.runtime_id.as_str().to_string(),
|
runtime_id: worker.runtime_id.as_str().to_string(),
|
||||||
runtime_worker_id: worker.worker_id.as_str().to_string(),
|
runtime_worker_id: worker.worker_id.as_str().to_string(),
|
||||||
display_name: display_name.to_string(),
|
display_name,
|
||||||
profile,
|
profile,
|
||||||
retention_state: existing
|
retention_state: existing
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|
@ -3994,7 +4043,13 @@ fn sync_worker_observation(
|
||||||
api: &WorkspaceApi,
|
api: &WorkspaceApi,
|
||||||
worker: &WorkerSummary,
|
worker: &WorkerSummary,
|
||||||
) -> ApiResult<WorkerRegistryRecord> {
|
) -> ApiResult<WorkerRegistryRecord> {
|
||||||
let record = record_worker_summary(api, worker, worker.label.as_str(), worker.profile.clone())?;
|
let record = record_worker_summary(
|
||||||
|
api,
|
||||||
|
worker,
|
||||||
|
worker.label.as_str(),
|
||||||
|
worker.profile.clone(),
|
||||||
|
WorkerRegistryDisplayNamePolicy::PreserveExisting,
|
||||||
|
)?;
|
||||||
if let Some(working_directory) = worker.working_directory.as_ref() {
|
if let Some(working_directory) = worker.working_directory.as_ref() {
|
||||||
let management_kind = api
|
let management_kind = api
|
||||||
.store
|
.store
|
||||||
|
|
@ -6298,6 +6353,23 @@ mod tests {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(created["runtime_id"], "embedded-worker-runtime");
|
assert_eq!(created["runtime_id"], "embedded-worker-runtime");
|
||||||
|
let workers = get_json(app.clone(), "/api/workers").await;
|
||||||
|
let worker = workers["items"]
|
||||||
|
.as_array()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.find(|worker| worker["worker_id"] == created["worker_id"])
|
||||||
|
.expect("created Worker should be listed");
|
||||||
|
assert_eq!(worker["label"], "Coding Worker");
|
||||||
|
assert_eq!(worker["worker_id"], created["worker_id"]);
|
||||||
|
let detail_path = format!(
|
||||||
|
"/api/runtimes/{}/workers/{}",
|
||||||
|
created["runtime_id"].as_str().unwrap(),
|
||||||
|
created["worker_id"].as_str().unwrap()
|
||||||
|
);
|
||||||
|
let detail = get_json(app.clone(), detail_path.as_str()).await;
|
||||||
|
assert_eq!(detail["label"], "Coding Worker");
|
||||||
|
assert_eq!(detail["worker_id"], created["worker_id"]);
|
||||||
assert!(
|
assert!(
|
||||||
created["console_href"]
|
created["console_href"]
|
||||||
.as_str()
|
.as_str()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user