parallel-codex-tui 0.3.1 → 0.4.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 +19 -8
- package/dist/cli.js +22 -2
- package/dist/core/session-index.js +123 -10
- package/dist/core/session-manager.js +15 -4
- package/dist/core/task-report.js +510 -0
- package/dist/core/task-search.js +142 -0
- package/dist/orchestrator/orchestrator.js +26 -4
- package/dist/supervisor/client.js +442 -0
- package/dist/supervisor/protocol.js +177 -0
- package/dist/supervisor/runner.js +238 -0
- package/dist/supervisor/store.js +213 -0
- package/dist/tui/App.js +169 -36
- package/dist/tui/AppShell.js +7 -3
- package/dist/tui/InputBar.js +20 -6
- package/dist/tui/TaskSessionsView.js +30 -9
- package/dist/version.js +1 -1
- package/dist/workers/mock-adapter.js +18 -0
- package/package.json +1 -1
|
@@ -2,13 +2,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Box, Text } from "ink";
|
|
3
3
|
import { compactEndByDisplayWidth, displayWidth } from "./display-width.js";
|
|
4
4
|
import { TUI_THEME } from "./theme.js";
|
|
5
|
-
export function TaskSessionsView({ tasks, activeTaskId, selectedIndex, includeArchived = false, notice = null, action = null, loading = false, error = null, height = 20, terminalWidth = process.stdout.columns || 120 }) {
|
|
5
|
+
export function TaskSessionsView({ tasks, activeTaskId, selectedIndex, includeArchived = false, query = "", notice = null, action = null, loading = false, error = null, height = 20, terminalWidth = process.stdout.columns || 120 }) {
|
|
6
6
|
const viewportHeight = Math.max(1, height);
|
|
7
7
|
const width = taskSessionsContentWidth(terminalWidth);
|
|
8
8
|
const lines = taskSessionsDisplayLines(tasks, activeTaskId, selectedIndex, viewportHeight, terminalWidth, {
|
|
9
9
|
loading,
|
|
10
10
|
error,
|
|
11
11
|
includeArchived,
|
|
12
|
+
query,
|
|
12
13
|
notice,
|
|
13
14
|
action
|
|
14
15
|
});
|
|
@@ -21,7 +22,10 @@ export function taskSessionsDisplayLines(tasks, activeTaskId, selectedIndex, hei
|
|
|
21
22
|
const lines = [
|
|
22
23
|
{
|
|
23
24
|
text: fitTaskSessionCandidates([
|
|
24
|
-
state.includeArchived
|
|
25
|
+
taskSessionsHeading(Boolean(state.includeArchived), state.query ?? ""),
|
|
26
|
+
...((state.query ?? "").trim()
|
|
27
|
+
? [`Find · ${safeTaskSessionText(state.query ?? "")}`, `/ ${safeTaskSessionText(state.query ?? "")}`]
|
|
28
|
+
: []),
|
|
25
29
|
state.includeArchived ? "Sessions · all" : "Sessions",
|
|
26
30
|
"Tasks",
|
|
27
31
|
"T"
|
|
@@ -30,7 +34,7 @@ export function taskSessionsDisplayLines(tasks, activeTaskId, selectedIndex, hei
|
|
|
30
34
|
}
|
|
31
35
|
];
|
|
32
36
|
if (viewportHeight >= 3) {
|
|
33
|
-
lines.push({ text: taskSessionSummary(tasks, width), tone: "muted" });
|
|
37
|
+
lines.push({ text: taskSessionSummary(tasks, width, state.query ?? ""), tone: "muted" });
|
|
34
38
|
}
|
|
35
39
|
if (viewportHeight >= 4 && state.action) {
|
|
36
40
|
lines.push({
|
|
@@ -58,7 +62,10 @@ export function taskSessionsDisplayLines(tasks, activeTaskId, selectedIndex, hei
|
|
|
58
62
|
}
|
|
59
63
|
if (tasks.length === 0) {
|
|
60
64
|
if (slots > 0) {
|
|
61
|
-
lines.push({
|
|
65
|
+
lines.push({
|
|
66
|
+
text: fitTaskSessionText(state.query?.trim() ? "No matching task sessions" : "No saved task sessions", width),
|
|
67
|
+
tone: "muted"
|
|
68
|
+
});
|
|
62
69
|
}
|
|
63
70
|
return lines;
|
|
64
71
|
}
|
|
@@ -94,7 +101,7 @@ function TaskSessionRow({ line, width }) {
|
|
|
94
101
|
const theme = taskSessionLineTheme(line.tone);
|
|
95
102
|
return (_jsxs(Text, { children: [_jsx(Text, { ...theme, children: line.text }), trailingWidth > 0 ? _jsx(Text, { backgroundColor: TUI_THEME.surface, children: " ".repeat(trailingWidth) }) : null] }));
|
|
96
103
|
}
|
|
97
|
-
function taskSessionSummary(tasks, width) {
|
|
104
|
+
function taskSessionSummary(tasks, width, query) {
|
|
98
105
|
const counts = new Map();
|
|
99
106
|
let archived = 0;
|
|
100
107
|
for (const task of tasks) {
|
|
@@ -112,11 +119,16 @@ function taskSessionSummary(tasks, width) {
|
|
|
112
119
|
if (archived > 0) {
|
|
113
120
|
parts.push(`${archived} archived`);
|
|
114
121
|
}
|
|
122
|
+
const searching = Boolean(query.trim());
|
|
123
|
+
const prefix = searching
|
|
124
|
+
? `${tasks.length} ${tasks.length === 1 ? "match" : "matches"}`
|
|
125
|
+
: `${tasks.length} ${tasks.length === 1 ? "task" : "tasks"}`;
|
|
126
|
+
const compactPrefix = searching ? `${tasks.length} matches` : `${tasks.length} tasks`;
|
|
115
127
|
return fitTaskSessionCandidates([
|
|
116
|
-
[
|
|
117
|
-
`${
|
|
118
|
-
|
|
119
|
-
`${tasks.length}t`
|
|
128
|
+
[prefix, ...parts].join(" · "),
|
|
129
|
+
`${compactPrefix} · ${counts.get("running") ?? 0} active · ${counts.get("failed") ?? 0} failed`,
|
|
130
|
+
compactPrefix,
|
|
131
|
+
`${tasks.length}${searching ? "m" : "t"}`
|
|
120
132
|
], width);
|
|
121
133
|
}
|
|
122
134
|
function taskSessionRowText(task, selected, active, width) {
|
|
@@ -130,7 +142,9 @@ function taskSessionRowText(task, selected, active, width) {
|
|
|
130
142
|
const workers = `${task.workerCount} ${task.workerCount === 1 ? "worker" : "workers"}`;
|
|
131
143
|
const native = `${task.nativeSessionCount} native`;
|
|
132
144
|
const compactId = task.id.replace(/^task-/, "#");
|
|
145
|
+
const match = safeTaskSessionText(task.searchMatch?.summary ?? "");
|
|
133
146
|
return fitTaskSessionCandidates([
|
|
147
|
+
...(match ? [[marker + title, status, match].join(" · ")] : []),
|
|
134
148
|
[marker + title, status, turns, workers, native, date].join(" · "),
|
|
135
149
|
[marker + title, status, turns, workers, native].join(" · "),
|
|
136
150
|
[marker + title, status, turns, workers].join(" · "),
|
|
@@ -139,6 +153,13 @@ function taskSessionRowText(task, selected, active, width) {
|
|
|
139
153
|
marker.trimEnd()
|
|
140
154
|
], width);
|
|
141
155
|
}
|
|
156
|
+
function taskSessionsHeading(includeArchived, query) {
|
|
157
|
+
const scope = includeArchived ? "archived shown" : "active";
|
|
158
|
+
const cleanQuery = safeTaskSessionText(query);
|
|
159
|
+
return cleanQuery
|
|
160
|
+
? `Task sessions · ${scope} · find ${cleanQuery}`
|
|
161
|
+
: includeArchived ? "Task sessions · archived shown" : "Task sessions";
|
|
162
|
+
}
|
|
142
163
|
function taskSessionWindowStart(selected, count, visibleCount) {
|
|
143
164
|
if (visibleCount <= 0 || count <= visibleCount) {
|
|
144
165
|
return 0;
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = "0.
|
|
1
|
+
export const version = "0.4.0";
|
|
@@ -10,6 +10,7 @@ export class MockWorkerAdapter {
|
|
|
10
10
|
await spec.onNativeSession?.(nativeSessionId);
|
|
11
11
|
await setStatus(spec, "running", "mock-running", `${spec.role} mock worker running`, nativeSessionId);
|
|
12
12
|
await appendText(spec.outputLogPath, `[mock:${spec.role}] started\n`);
|
|
13
|
+
await waitForConfiguredMockDelay(spec);
|
|
13
14
|
if (spec.role === "judge") {
|
|
14
15
|
if (spec.prompt.includes("# Role:") && spec.prompt.includes("· Final acceptance")) {
|
|
15
16
|
const criterionIds = promptJsonArray(spec.prompt, "Required acceptance criterion ids");
|
|
@@ -67,6 +68,23 @@ export class MockWorkerAdapter {
|
|
|
67
68
|
};
|
|
68
69
|
}
|
|
69
70
|
}
|
|
71
|
+
async function waitForConfiguredMockDelay(spec) {
|
|
72
|
+
const configured = Number(spec.modelConfig?.env?.PCT_MOCK_DELAY_MS ?? 0);
|
|
73
|
+
const delayMs = Number.isFinite(configured) ? Math.min(10000, Math.max(0, Math.trunc(configured))) : 0;
|
|
74
|
+
if (delayMs === 0 || spec.signal?.aborted) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
await new Promise((resolve) => {
|
|
78
|
+
const timer = setTimeout(finish, delayMs);
|
|
79
|
+
const signal = spec.signal;
|
|
80
|
+
function finish() {
|
|
81
|
+
clearTimeout(timer);
|
|
82
|
+
signal?.removeEventListener("abort", finish);
|
|
83
|
+
resolve();
|
|
84
|
+
}
|
|
85
|
+
signal?.addEventListener("abort", finish, { once: true });
|
|
86
|
+
});
|
|
87
|
+
}
|
|
70
88
|
async function cancelMockWorker(spec, nativeSessionId) {
|
|
71
89
|
await appendText(spec.outputLogPath, "[mock] cancelled\n");
|
|
72
90
|
await setStatus(spec, "cancelled", "mock-cancelled", `${spec.role} mock worker cancelled`, nativeSessionId);
|