taskchef 7.15.0 → 7.15.2

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.0",
3
+ "version": "7.15.2",
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.0",
3
+ "version": "7.15.2",
4
4
  "description": "A non-blocking interactive dispatcher for visible Codex tasks.",
5
5
  "license": "MIT",
6
6
  "author": "Favo Yang",
@@ -61,13 +61,23 @@ const elements = {
61
61
  };
62
62
  let notificationDescriptionSerial = 0;
63
63
 
64
- function referenceLink(link, { compact = false } = {}) {
64
+ function typedReferenceLabel(link, label, typePrefix) {
65
+ if (!typePrefix) return label;
66
+ if (link.type === "pull") return `PR ${label}`;
67
+ if (link.type === "issue") return `Issue ${label}`;
68
+ return label;
69
+ }
70
+
71
+ function referenceLink(link, { compact = false, displayLabel, typePrefix = false } = {}) {
65
72
  const anchor = document.createElement("a");
66
73
  anchor.className = compact ? "github-link github-link-compact" : "github-link";
67
74
  anchor.href = link.url;
68
75
  anchor.target = "_blank";
69
76
  anchor.rel = "noopener noreferrer";
70
- anchor.textContent = link.label ?? link.text;
77
+ const label = link.label ?? link.text;
78
+ const visibleLabel = typedReferenceLabel(link, displayLabel ?? label, typePrefix);
79
+ const accessibleLabel = typedReferenceLabel(link, label, typePrefix);
80
+ anchor.textContent = visibleLabel;
71
81
  const githubKind = link.type === "issue"
72
82
  ? ", GitHub issue"
73
83
  : link.type === "pull"
@@ -75,7 +85,7 @@ function referenceLink(link, { compact = false } = {}) {
75
85
  : link.provider === "github" || link.owner ? " on GitHub" : "";
76
86
  anchor.setAttribute(
77
87
  "aria-label",
78
- `${link.label ?? link.text}${githubKind} (opens in a new tab)`,
88
+ `${accessibleLabel}${githubKind} (opens in a new tab)`,
79
89
  );
80
90
  anchor.addEventListener("click", (event) => event.stopPropagation());
81
91
  return anchor;
@@ -87,7 +97,7 @@ function appendLinkedText(container, text, task) {
87
97
  taskRepository: task.relatedGitHubRepository,
88
98
  }).map((segment) => {
89
99
  if (segment.kind === "text") return document.createTextNode(segment.text);
90
- if (segment.kind === "link") return referenceLink(segment);
100
+ if (segment.kind === "link") return referenceLink(segment, { typePrefix: true });
91
101
  const ambiguous = document.createElement("span");
92
102
  ambiguous.className = "github-reference-ambiguous";
93
103
  ambiguous.textContent = segment.text;
@@ -100,11 +110,27 @@ function appendLinkedText(container, text, task) {
100
110
  }
101
111
 
102
112
  function relatedGitHubLinks(task, { compact = false } = {}) {
103
- const links = task.relatedGitHubLinks ?? [];
113
+ const seen = new Set();
114
+ const links = (task.relatedGitHubLinks ?? []).filter((link) => {
115
+ if (link.type === "repository" || seen.has(link.label)) return false;
116
+ seen.add(link.label);
117
+ return true;
118
+ });
104
119
  const container = document.createElement("nav");
105
120
  container.className = `github-links${compact ? " github-links-compact" : ""}`;
106
121
  container.setAttribute("aria-label", `Related GitHub links for ${task.title}`);
107
- const children = links.map((link) => referenceLink(link, { compact }));
122
+ const seenRepositories = new Set();
123
+ const children = links.map((link) => {
124
+ const repository = link.owner && link.repository
125
+ ? `${link.owner}/${link.repository}`
126
+ : null;
127
+ const repeatedRepository = repository && seenRepositories.has(repository);
128
+ if (repository) seenRepositories.add(repository);
129
+ const displayLabel = repeatedRepository && link.number
130
+ ? `#${link.number}`
131
+ : link.label;
132
+ return referenceLink(link, { compact, displayLabel, typePrefix: true });
133
+ });
108
134
  if (task.relatedGitHubLinksTruncated) {
109
135
  const more = document.createElement("span");
110
136
  more.className = "github-links-more";
@@ -118,6 +144,26 @@ function relatedGitHubLinks(task, { compact = false } = {}) {
118
144
  return container;
119
145
  }
120
146
 
147
+ function renderProject(container, task) {
148
+ const children = [document.createTextNode(task.project.name)];
149
+ const repository = task.relatedGitHubRepository;
150
+ if (repository) {
151
+ const [owner, repositoryName] = repository.split("/");
152
+ children.push(
153
+ document.createTextNode(" "),
154
+ referenceLink({
155
+ label: repository,
156
+ owner,
157
+ provider: "github",
158
+ repository: repositoryName,
159
+ type: "repository",
160
+ url: `https://github.com/${repository}`,
161
+ }),
162
+ );
163
+ }
164
+ container.replaceChildren(...children);
165
+ }
166
+
121
167
  function timestampControl(value, { accessibleName, key, prefix = "" }) {
122
168
  if (!parsedTimestamp(value)) {
123
169
  const missing = document.createElement("span");
@@ -340,7 +386,7 @@ function renderDialog(task) {
340
386
  results: task.results ?? preservedResults ?? [],
341
387
  };
342
388
  state.selectedTask = detailedTask;
343
- elements.dialogProject.textContent = task.project.name;
389
+ renderProject(elements.dialogProject, task);
344
390
  elements.dialogTitle.textContent = task.title;
345
391
  elements.dialogRelatedLinks.replaceChildren(...relatedGitHubLinks(detailedTask).children);
346
392
  elements.dialogRelatedLinks.setAttribute(
@@ -421,7 +467,7 @@ function taskCard(task) {
421
467
  heading.append(title, badge);
422
468
  const project = document.createElement("p");
423
469
  project.className = "task-project";
424
- project.textContent = task.project.name;
470
+ renderProject(project, task);
425
471
  const summary = document.createElement("p");
426
472
  summary.className = "task-summary";
427
473
  const latest = latestTurnPresentation(task);
@@ -323,7 +323,8 @@ export function taskGitHubProjection(task) {
323
323
  taskRepository,
324
324
  })) {
325
325
  if (segment.kind !== "link") continue;
326
- const key = segment.url;
326
+ if (segment.type === "repository") continue;
327
+ const key = relatedLinkLabel(segment);
327
328
  if (seen.has(key)) continue;
328
329
  if (links.length === MAX_RELATED_GITHUB_LINKS) {
329
330
  truncated = true;