taskchef 7.15.5 → 7.15.6

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskchef",
3
- "version": "7.15.5",
3
+ "version": "7.15.6",
4
4
  "description": "Dispatch work from a data-only workspace to visible Codex project tasks.",
5
5
  "author": {
6
6
  "name": "Favo Yang",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "taskchef",
3
- "version": "7.15.5",
3
+ "version": "7.15.6",
4
4
  "description": "A non-blocking interactive dispatcher for visible Codex tasks.",
5
5
  "license": "MIT",
6
6
  "author": "Favo Yang",
@@ -29,6 +29,8 @@ const state = {
29
29
  };
30
30
  let dateRefreshTimer = null;
31
31
  let detailRequestGeneration = 0;
32
+ let copyTaskIdGeneration = 0;
33
+ let copyTaskIdTimer = null;
32
34
  const relativeTimes = new RelativeTimeController();
33
35
 
34
36
  const elements = {
@@ -36,7 +38,7 @@ const elements = {
36
38
  closeDialog: document.querySelector("#close-dialog"),
37
39
  connectionDot: document.querySelector("#connection-dot"),
38
40
  connectionLabel: document.querySelector("#connection-label"),
39
- copyThreadId: document.querySelector("#copy-thread-id"),
41
+ copyTaskId: document.querySelector("#copy-task-id"),
40
42
  dashboardMessage: document.querySelector("#dashboard-message"),
41
43
  dashboardMessageText: document.querySelector("#dashboard-message-text"),
42
44
  dateFilter: document.querySelector("#date-filter"),
@@ -211,6 +213,11 @@ function configureOpenTaskControl(control, ariaLabel) {
211
213
  control.replaceChildren(codexIcon(), label);
212
214
  }
213
215
 
216
+ function setCopyTaskIdLabel(label) {
217
+ elements.copyTaskId.textContent = label;
218
+ elements.copyTaskId.setAttribute("aria-label", label);
219
+ }
220
+
214
221
  function setConnection(connected) {
215
222
  elements.connectionDot.classList.toggle("connected", connected);
216
223
  elements.connectionLabel.textContent = connected ? "Live" : "Reconnecting…";
@@ -377,6 +384,11 @@ function turnTimeline(task) {
377
384
  }
378
385
 
379
386
  function renderDialog(task) {
387
+ if (state.selectedTask?.id !== task.id) {
388
+ copyTaskIdGeneration += 1;
389
+ clearTimeout(copyTaskIdTimer);
390
+ copyTaskIdTimer = null;
391
+ }
380
392
  const preservedResults = state.selectedTask?.id === task.id
381
393
  ? state.selectedTask.results
382
394
  : null;
@@ -398,7 +410,8 @@ function renderDialog(task) {
398
410
  );
399
411
  elements.dialogResults.replaceChildren(...turnTimeline(detailedTask));
400
412
  elements.dialogInstruction.textContent = task.instruction;
401
- elements.copyThreadId.disabled = !task.threadId;
413
+ elements.copyTaskId.disabled = !task.id;
414
+ setCopyTaskIdLabel("Copy Task ID");
402
415
  elements.dialogMetadata.replaceChildren(
403
416
  ...detailRow("Current status", taskStatusLabel(task)),
404
417
  ...detailRow("Current turn ref", task.turnRef),
@@ -607,14 +620,26 @@ elements.closeDialog.addEventListener("click", () => elements.dialog.close());
607
620
  elements.dialog.addEventListener("click", (event) => {
608
621
  if (event.target === elements.dialog) elements.dialog.close();
609
622
  });
610
- elements.copyThreadId.addEventListener("click", async () => {
611
- if (!state.selectedTask?.threadId) return;
623
+ elements.copyTaskId.addEventListener("click", async () => {
624
+ const taskId = state.selectedTask?.id;
625
+ if (!taskId) return;
626
+ const copyGeneration = ++copyTaskIdGeneration;
627
+ clearTimeout(copyTaskIdTimer);
628
+ copyTaskIdTimer = null;
612
629
  try {
613
- await navigator.clipboard.writeText(state.selectedTask.threadId);
614
- elements.copyThreadId.textContent = "Copied";
615
- setTimeout(() => { elements.copyThreadId.textContent = "Copy thread ID"; }, 1_500);
630
+ await navigator.clipboard.writeText(taskId);
631
+ if (copyGeneration !== copyTaskIdGeneration || state.selectedTask?.id !== taskId) return;
632
+ setCopyTaskIdLabel("Task ID copied");
633
+ copyTaskIdTimer = setTimeout(() => {
634
+ if (copyGeneration === copyTaskIdGeneration && state.selectedTask?.id === taskId) {
635
+ setCopyTaskIdLabel("Copy Task ID");
636
+ }
637
+ copyTaskIdTimer = null;
638
+ }, 1_500);
616
639
  } catch {
617
- showMessage("Clipboard access is unavailable. Copy the thread ID from the metadata below.");
640
+ if (copyGeneration === copyTaskIdGeneration && state.selectedTask?.id === taskId) {
641
+ showMessage("Clipboard access is unavailable. Copy the Task ID from the metadata below.");
642
+ }
618
643
  }
619
644
  });
620
645
  elements.openProject.addEventListener("click", async (event) => {
@@ -112,7 +112,7 @@
112
112
  </picture>
113
113
  <span>Open task</span>
114
114
  </button>
115
- <button id="copy-thread-id" class="secondary-button" type="button">Copy thread ID</button>
115
+ <button id="copy-task-id" class="secondary-button" type="button" aria-label="Copy Task ID">Copy Task ID</button>
116
116
  </div>
117
117
  <nav id="dialog-related-links" class="github-links" aria-label="Related GitHub links" hidden></nav>
118
118
  <section>