taskchef 7.7.1 → 7.8.0
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.
package/README.md
CHANGED
|
@@ -176,6 +176,8 @@ taskchef dashboard --port 3211
|
|
|
176
176
|
The loopback dashboard watches `tasks.jsonl`, groups current states, and opens
|
|
177
177
|
linked Codex tasks. List snapshots and SSE events carry only the latest-result
|
|
178
178
|
projection; opening task details fetches the full newest-first result history.
|
|
179
|
+
The header shows the running TaskChef package version reported by the same
|
|
180
|
+
bounded health identity used for compatible-listener checks.
|
|
179
181
|
Task and result times are relative through 29 days (with minute detail for the
|
|
180
182
|
first six hours), then use a locale-aware calendar date. Each time is a keyboard-
|
|
181
183
|
accessible toggle for its full locale-aware date and time, and one shared
|
|
@@ -197,6 +199,8 @@ The health endpoint contains only a fixed service marker, health schema,
|
|
|
197
199
|
TaskChef version, dashboard-server version, and canonical workspace. It exposes
|
|
198
200
|
no task data, credentials, environment variables, process control, or secrets.
|
|
199
201
|
|
|
202
|
+

|
|
203
|
+
|
|
200
204
|

|
|
201
205
|
|
|
202
206
|

|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "taskchef",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.8.0",
|
|
4
4
|
"description": "A non-blocking interactive dispatcher for visible Codex tasks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Favo Yang",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"docs/spec.md",
|
|
27
27
|
"docs/workflows.md",
|
|
28
28
|
"docs/firstmate-taskchef-comparison.md",
|
|
29
|
+
"docs/images/dashboard-identity.jpg",
|
|
29
30
|
"docs/images/notification-event-snapshots.jpg",
|
|
30
31
|
"docs/images/result-history-dashboard.jpg",
|
|
31
32
|
"index.js",
|
package/src/dashboard/app.js
CHANGED
|
@@ -49,6 +49,7 @@ const elements = {
|
|
|
49
49
|
projectFilter: document.querySelector("#project-filter"),
|
|
50
50
|
statusFilter: document.querySelector("#status-filter"),
|
|
51
51
|
taskCount: document.querySelector("#task-count"),
|
|
52
|
+
taskchefVersion: document.querySelector("#taskchef-version"),
|
|
52
53
|
taskList: document.querySelector("#task-list"),
|
|
53
54
|
toastList: document.querySelector("#toast-list"),
|
|
54
55
|
};
|
|
@@ -87,8 +88,8 @@ function codexIcon() {
|
|
|
87
88
|
const image = document.createElement("img");
|
|
88
89
|
image.src = "/assets/codex-app-light.png";
|
|
89
90
|
image.alt = "";
|
|
90
|
-
image.width =
|
|
91
|
-
image.height =
|
|
91
|
+
image.width = 18;
|
|
92
|
+
image.height = 18;
|
|
92
93
|
picture.append(dark, image);
|
|
93
94
|
return picture;
|
|
94
95
|
}
|
|
@@ -106,6 +107,22 @@ function setConnection(connected) {
|
|
|
106
107
|
elements.connectionLabel.textContent = connected ? "Live" : "Reconnecting…";
|
|
107
108
|
}
|
|
108
109
|
|
|
110
|
+
async function loadDashboardVersion() {
|
|
111
|
+
try {
|
|
112
|
+
const response = await fetch("/api/health");
|
|
113
|
+
if (!response.ok) return;
|
|
114
|
+
const identity = await response.json();
|
|
115
|
+
if (typeof identity.taskchefVersion !== "string" || !identity.taskchefVersion) return;
|
|
116
|
+
elements.taskchefVersion.textContent = `v${identity.taskchefVersion}`;
|
|
117
|
+
elements.taskchefVersion.setAttribute(
|
|
118
|
+
"aria-label",
|
|
119
|
+
`TaskChef version ${identity.taskchefVersion}`,
|
|
120
|
+
);
|
|
121
|
+
} catch {
|
|
122
|
+
// The live connection state already communicates dashboard availability.
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
109
126
|
function replaceOptions(select, values, allLabel) {
|
|
110
127
|
const selected = select.value;
|
|
111
128
|
select.replaceChildren();
|
|
@@ -399,6 +416,8 @@ function showMessage(message) {
|
|
|
399
416
|
elements.dashboardMessage.hidden = false;
|
|
400
417
|
}
|
|
401
418
|
|
|
419
|
+
void loadDashboardVersion();
|
|
420
|
+
|
|
402
421
|
const events = new EventSource("/api/events");
|
|
403
422
|
events.addEventListener("open", () => setConnection(true));
|
|
404
423
|
events.addEventListener("error", () => setConnection(false));
|
package/src/dashboard/index.html
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<body>
|
|
12
12
|
<header class="site-header">
|
|
13
13
|
<div>
|
|
14
|
-
<p class="eyebrow">TaskChef
|
|
14
|
+
<p class="eyebrow">TaskChef <span id="taskchef-version" class="dashboard-version"></span></p>
|
|
15
15
|
<div class="title-row">
|
|
16
16
|
<picture class="dashboard-icon" aria-hidden="true">
|
|
17
17
|
<source srcset="/assets/taskchef-dark.svg" media="(prefers-color-scheme: dark)">
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
<button id="open-codex" class="primary-button task-action" type="button" aria-label="Open this task in Codex">
|
|
88
88
|
<picture class="codex-icon" aria-hidden="true">
|
|
89
89
|
<source srcset="/assets/codex-app-dark.png" media="(prefers-color-scheme: dark)">
|
|
90
|
-
<img src="/assets/codex-app-light.png" alt="" width="
|
|
90
|
+
<img src="/assets/codex-app-light.png" alt="" width="18" height="18">
|
|
91
91
|
</picture>
|
|
92
92
|
<span>Open task</span>
|
|
93
93
|
</button>
|
package/src/dashboard/styles.css
CHANGED
|
@@ -51,6 +51,7 @@ h3 { margin-bottom: 8px; font-size: 0.84rem; letter-spacing: 0.08em; text-transf
|
|
|
51
51
|
.dashboard-icon img { display: block; width: 100%; height: 100%; object-fit: contain; }
|
|
52
52
|
|
|
53
53
|
.eyebrow { margin-bottom: 10px; color: var(--accent); font-size: 0.78rem; font-weight: 750; letter-spacing: 0.15em; text-transform: uppercase; }
|
|
54
|
+
.dashboard-version { margin-inline-start: 0.45em; color: var(--muted); font-size: 0.72rem; letter-spacing: 0.04em; text-transform: none; }
|
|
54
55
|
.subtitle, .task-project, time, .timestamp-missing { color: var(--muted); }
|
|
55
56
|
.subtitle { margin-bottom: 0; }
|
|
56
57
|
|
|
@@ -71,12 +72,13 @@ label { display: grid; gap: 6px; color: var(--muted); font-size: 0.78rem; font-w
|
|
|
71
72
|
select { min-width: 180px; padding: 9px 34px 9px 11px; border: 1px solid var(--border); border-radius: 7px; background: var(--surface); color: var(--text); }
|
|
72
73
|
.task-count { margin: 0 0 9px auto; color: var(--muted); font-size: 0.9rem; }
|
|
73
74
|
|
|
74
|
-
.task-list { display: grid; gap: 12px; }
|
|
75
|
+
.task-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
|
|
75
76
|
.task-card { padding: 20px 22px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); box-shadow: 0 1px 0 rgb(0 0 0 / 2%); }
|
|
76
77
|
.task-heading { display: flex; align-items: flex-start; justify-content: space-between; gap: 18px; }
|
|
77
78
|
.task-title { padding: 0; border: 0; background: none; font-size: 1.08rem; font-weight: 720; text-align: left; cursor: pointer; }
|
|
78
79
|
.task-title:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
|
|
79
80
|
.task-project { margin: 3px 0 12px; font-size: 0.86rem; }
|
|
81
|
+
.task-title, .task-summary { overflow-wrap: anywhere; }
|
|
80
82
|
.task-summary { max-width: 78ch; margin-bottom: 14px; }
|
|
81
83
|
time, .timestamp-missing { font-size: 0.78rem; }
|
|
82
84
|
.timestamp-toggle { padding: 2px 0; border: 0; background: none; cursor: pointer; text-align: left; }
|
|
@@ -84,7 +86,7 @@ time, .timestamp-missing { font-size: 0.78rem; }
|
|
|
84
86
|
.task-footer { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
|
|
85
87
|
.task-open { flex: none; }
|
|
86
88
|
.task-action { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 32px; padding: 5px 9px; font-size: 0.82rem; line-height: 1.2; white-space: nowrap; }
|
|
87
|
-
.codex-icon { display: block; flex: none; width:
|
|
89
|
+
.codex-icon { display: block; flex: none; width: 18px; height: 18px; }
|
|
88
90
|
.codex-icon img { display: block; width: 100%; height: 100%; object-fit: contain; }
|
|
89
91
|
|
|
90
92
|
.status { flex: none; padding: 4px 9px; border-radius: 999px; background: var(--surface-muted); color: var(--muted); font-size: 0.72rem; font-weight: 750; text-transform: capitalize; }
|