taskchef 9.0.0 → 9.0.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.
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +6 -2
- package/docs/mcp-app.md +21 -4
- package/package.json +1 -1
- package/src/codex-session-scanner.js +11 -3
- package/src/mcp-app/dist/index.html +56 -51
- package/src/mcp-app/react/NextTaskDetail.test.tsx +14 -0
- package/src/mcp-app/react/styles.css +7 -0
- package/src/ui/components/TaskBoard.test.tsx +11 -0
- package/src/ui/components/TurnContent.test.tsx +13 -0
- package/src/ui/components/TurnContent.tsx +5 -2
- package/src/ui/types.ts +1 -0
- package/src/user-prompt.js +11 -0
package/README.md
CHANGED
|
@@ -39,8 +39,12 @@ npm run check:mcp-app
|
|
|
39
39
|
npm run build:mcp-app
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
Develop on a topic branch and update **TaskChef Dev** first. Keep **TaskChef**
|
|
43
|
+
on the published release. After validation, independent review, merge, and a
|
|
44
|
+
successful release workflow, update TaskChef from the released package when
|
|
45
|
+
the merge publishes a release. Otherwise keep its existing published version.
|
|
46
|
+
The Dev copy uses the separate `taskchef-next` plugin ID and **TaskChef Dev**
|
|
47
|
+
name; apply that identity only to its local staging package. See
|
|
44
48
|
[development packaging](docs/mcp-app.md#development-plugin-identity).
|
|
45
49
|
|
|
46
50
|
[Native app guide](docs/mcp-app.md) · [GitHub setup](docs/taskchef-next-github.md)
|
package/docs/mcp-app.md
CHANGED
|
@@ -45,7 +45,7 @@ See the [storage schema](taskchef-next-storage.md), including the editable diagr
|
|
|
45
45
|
|
|
46
46
|
### TaskChef card content
|
|
47
47
|
|
|
48
|
-
Cards show the chat title, project, a plain two-line preview, activity time, and Open chat. Running cards show the current request; other cards show the latest response. Excerpts are capped at 2,000 characters. Actual scheduled inputs display the recorded heartbeat instructions, even after the schedule is removed. No model summarizes or judges the text.
|
|
48
|
+
Cards show the chat title, project, a plain two-line preview, activity time, and Open chat. Running cards show the current request; other cards show the latest response. Interrupted cards also show the latest turn’s recorded error message, when available. Details show the same message in a rounded notice after the response. A new running or completed turn clears the notice. Excerpts are capped at 2,000 characters. Actual scheduled inputs display the recorded heartbeat instructions, even after the schedule is removed. No model summarizes or judges the text.
|
|
49
49
|
|
|
50
50
|
Details pairs the full recorded latest-turn request and response, each initially capped at three lines with independent Show more/Show less controls. Selected quotes render as Markdown quotes and file/image references as named attachments. Generated request headings and context metadata are hidden in the display. Recorded input remains unchanged. Raw HTML is ignored and relative file links appear as text.
|
|
51
51
|
|
|
@@ -181,8 +181,25 @@ visibly and is preserved for repair.
|
|
|
181
181
|
## Development plugin identity
|
|
182
182
|
|
|
183
183
|
Keep the released **TaskChef** plugin and a separate **TaskChef Dev** plugin.
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
Use this order for every development change:
|
|
185
|
+
|
|
186
|
+
1. Work in a topic branch/worktree. Build and validate the current source.
|
|
187
|
+
2. Copy the current runtime, built UI, skill, and production dependencies into
|
|
188
|
+
a separate local staging package. Update **TaskChef Dev** from that package
|
|
189
|
+
and test it before merging. Never copy development changes into TaskChef's
|
|
190
|
+
released installation.
|
|
191
|
+
3. Pass independent review and the pull request checks, then merge when authorized.
|
|
192
|
+
4. If the merge publishes a release, wait for the complete release workflow,
|
|
193
|
+
including its marketplace update. Update **TaskChef** from the published
|
|
194
|
+
package and verify its version. If no release is published, leave TaskChef
|
|
195
|
+
on its existing published version.
|
|
196
|
+
|
|
197
|
+
For a full Dev update, give the staging package a unique development version
|
|
198
|
+
in both `package.json` and `.codex-plugin/plugin.json` (and package-lock metadata
|
|
199
|
+
if present), such as `9.0.0-dev.1`. Set only the staging manifest's plugin name
|
|
200
|
+
to `taskchef-next`; keep the source release manifest named `taskchef`.
|
|
201
|
+
Before installing the staging package through the local development marketplace,
|
|
202
|
+
run:
|
|
186
203
|
|
|
187
204
|
```sh
|
|
188
205
|
node scripts/prepare-mcp-app-preview.js /path/to/staging/plugin
|
|
@@ -209,7 +226,7 @@ From the source checkout, run:
|
|
|
209
226
|
npm run update:mcp-app-preview -- /path/to/the/running/taskchef-next/version
|
|
210
227
|
```
|
|
211
228
|
|
|
212
|
-
The helper builds the UI, checks the
|
|
229
|
+
The helper builds the UI, checks the development plugin ID is `taskchef-next`, and replaces only
|
|
213
230
|
`src/mcp-app/dist/index.html` atomically. It preserves the plugin version, server
|
|
214
231
|
code, dependencies, and local data. It refuses missing or redirected HTML paths.
|
|
215
232
|
Then right-click **TaskChef Dev** in the Codex sidebar and choose **Refresh**.
|
package/package.json
CHANGED
|
@@ -232,7 +232,8 @@ function readDatabaseRecords(state, history) {
|
|
|
232
232
|
const eligible = `coalesce(thread_source, '') NOT IN ('subagent', 'guardian_review')
|
|
233
233
|
AND CASE WHEN json_valid(source) THEN json_type(source, '$.subagent') IS NULL ELSE 1 END
|
|
234
234
|
AND NOT EXISTS (SELECT 1 FROM thread_spawn_edges WHERE child_thread_id = threads.id)`;
|
|
235
|
-
const
|
|
235
|
+
const hasTurnError = history.prepare("PRAGMA table_info(thread_turns)").all().some(column => column.name === "error_json");
|
|
236
|
+
const latestTurn = history.prepare(`SELECT turn_id, status, started_at, duration_ms, first_user_item_id, final_agent_item_id, ${hasTurnError ? "error_json" : "NULL AS error_json"}
|
|
236
237
|
FROM thread_turns WHERE thread_id = ? ORDER BY rollout_ordinal DESC LIMIT 1`);
|
|
237
238
|
const turns = new Map();
|
|
238
239
|
const needsAnswers = new Map();
|
|
@@ -334,6 +335,13 @@ function buildDatabaseSnapshot(records, now, doneMarks, schedules, scheduleError
|
|
|
334
335
|
const status = row.archived ? "archived" : manualDone ? "completed" : manualScheduled ? "scheduled" : active ? "working"
|
|
335
336
|
: ["failed", "interrupted"].includes(turn.status) ? "interrupted"
|
|
336
337
|
: turn.status === "completed" ? scheduled && inputSource === "scheduled" ? "scheduled" : "needs_input" : null;
|
|
338
|
+
let turnError = null;
|
|
339
|
+
if (status === "interrupted" && turn.error_json) {
|
|
340
|
+
try {
|
|
341
|
+
const error = JSON.parse(turn.error_json);
|
|
342
|
+
if (typeof error?.message === "string") turnError = error.message.trim() || null;
|
|
343
|
+
} catch { /* Invalid optional error metadata must not hide the chat. */ }
|
|
344
|
+
}
|
|
337
345
|
const statusLabel = status === "archived" ? "Archived" : status === "completed" ? "Done" : status === "working" ? "Running" : status === "needs_input" ? "Waiting for input/review" : status === "scheduled" ? "Scheduled" : status === "interrupted" ? "Interrupted" : "Unverified";
|
|
338
346
|
const reason = row.archived ? "Chat is archived." : manualDone ? "Marked Done in TaskChef. A new turn resets this mark."
|
|
339
347
|
: active ? "Latest selected turn is in progress."
|
|
@@ -344,7 +352,7 @@ function buildDatabaseSnapshot(records, now, doneMarks, schedules, scheduleError
|
|
|
344
352
|
return {
|
|
345
353
|
id: row.id, title: row.name?.trim() || row.title?.trim() || `Codex chat ${row.id.slice(0, 8)}`,
|
|
346
354
|
instruction: "Chat name and title are local metadata and can contain user text.",
|
|
347
|
-
summary: reason, promptExcerpt, replyExcerpt, annotations, promptImages, promptImage: promptImages[0] ?? null, replyImage: images.get(row.id),
|
|
355
|
+
summary: reason, turnError, promptExcerpt, replyExcerpt, annotations, promptImages, promptImage: promptImages[0] ?? null, replyImage: images.get(row.id),
|
|
348
356
|
needsAnswer: !row.archived && (records.needsAnswers.get(historyId(row))?.length ?? 0) > 0,
|
|
349
357
|
pendingQuestions: row.archived ? [] : records.needsAnswers.get(historyId(row)) ?? [],
|
|
350
358
|
status, statusLabel, scheduled, nextRunAt, manualDone, manualScheduled, inputSource,
|
|
@@ -542,7 +550,7 @@ export class CodexSessionScanner {
|
|
|
542
550
|
catch { throw new ProjectMetadataError("TaskChef cannot read Codex project metadata. Check .codex-global-state.json and the project worktree metadata, then refresh."); }
|
|
543
551
|
const nextTasks = new Map(grouped.tasks.map((task) => [task.id, task]));
|
|
544
552
|
const signature = (tasks) => JSON.stringify([...tasks.values()].map((task) => [
|
|
545
|
-
task.id, task.title, task.project.path, task.project.id, task.project.name, task.updatedAt, task.status, task.summary,
|
|
553
|
+
task.id, task.title, task.project.path, task.project.id, task.project.name, task.updatedAt, task.status, task.summary, task.turnError,
|
|
546
554
|
task.observed.archive, task.observed.unread, task.observed.lastTurnEvent, task.observed.directChildCount, task.observed.latestTurnDurationMs,
|
|
547
555
|
task.scheduled, task.nextRunAt, task.inputSource, task.turnId, task.promptExcerpt, task.replyExcerpt, task.annotations, task.promptImages, task.promptImage, task.replyImage, task.queuedPrompts, task.needsAnswer, task.pendingQuestions, task.pullRequests,
|
|
548
556
|
]));
|