workdir: project occupancy from links

This commit is contained in:
2026-07-24 09:29:25 +09:00
parent b1570aba63
commit e0b092dbc8
9 changed files with 202 additions and 21 deletions
@@ -115,6 +115,14 @@ export type WorkingDirectoryRepositoryOption = {
default_selector?: string | null;
};
export type WorkingDirectoryOccupancy = {
runtime_id: string;
runtime_worker_id: number;
worker_id: string;
display_name: string;
linked_at: string;
};
export type WorkingDirectorySummary = {
working_directory_id: string;
repository_id: string;
@@ -125,6 +133,7 @@ export type WorkingDirectorySummary = {
status: string;
cleanliness?: string | null;
primary_worker_id?: number | null;
occupied_by?: WorkingDirectoryOccupancy | null;
cleanup_target: {
kind: string;
working_directory_id: string;
@@ -86,6 +86,40 @@ Deno.test("defaultWorkerLaunchForm chooses active runtime, coder profile, reposi
assertEquals(form.working_directory_selector, "HEAD");
});
Deno.test("defaultWorkerLaunchForm skips occupied working directories", () => {
const form = defaultWorkerLaunchForm(
{
...options,
working_directories: [
{
...options.working_directories[0],
occupied_by: {
runtime_id: "embedded",
runtime_worker_id: 12,
worker_id: "embedded:12",
display_name: "Worker 12",
linked_at: "2026-07-24T00:00:00Z",
},
},
],
},
{
runtime_id: "",
display_name: "",
profile: "",
initial_text: "hello",
working_directory_id: "",
working_directory_repository_id: "",
working_directory_selector: "",
relative_cwd: "",
},
);
assertEquals(form.working_directory_id, "");
assertEquals(form.working_directory_repository_id, "repo");
assertEquals(form.working_directory_selector, "HEAD");
});
Deno.test("buildBrowserCreateWorkerRequest sends working_directory id and relative cwd only", () => {
const request = buildBrowserCreateWorkerRequest({
runtime_id: "embedded",
@@ -38,7 +38,8 @@ export function defaultWorkerLaunchForm(
const availableWorkingDirectories = options?.working_directories.filter((directory) =>
directory.status === "active" &&
directory.cleanliness === "clean" &&
directory.primary_worker_id == null
directory.primary_worker_id == null &&
directory.occupied_by == null
) ?? [];
const selectedRuntime = current.runtime_id
? options?.runtimes.find((runtime) => runtime.runtime_id === current.runtime_id)
@@ -129,6 +129,7 @@
<th>Commit</th>
<th>Status</th>
<th>Cleanliness</th>
<th>Occupied by</th>
<th>Action</th>
</tr>
</thead>
@@ -142,6 +143,14 @@
<td><code>{commitLabel(workdir)}</code></td>
<td>{workdir.status}</td>
<td>{workdir.cleanliness ?? 'unknown'}</td>
<td>
{#if workdir.occupied_by}
<span>{workdir.occupied_by.display_name}</span>
<small>{workdir.occupied_by.runtime_id}:{workdir.occupied_by.runtime_worker_id}</small>
{:else}
<span class="muted"></span>
{/if}
</td>
<td>
{#if cleanup}
<button
@@ -50,7 +50,10 @@
selectedRuntimeAllowsNoWorkdir
? []
: (options?.working_directories ?? []).filter((directory) =>
directory.status === 'active' && directory.cleanliness === 'clean' && directory.primary_worker_id == null
directory.status === 'active' &&
directory.cleanliness === 'clean' &&
directory.primary_worker_id == null &&
directory.occupied_by == null
),
);
let canStartWorker = $derived(Boolean(