@gavin-hu/my-pi-agent 0.21.0 → 0.22.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 +46 -31
- package/README.zh-CN.md +40 -26
- package/assets/screens/board.png +0 -0
- package/assets/screens/chrome.png +0 -0
- package/assets/screens/file-browse.png +0 -0
- package/assets/screens/plan-review.png +0 -0
- package/assets/screens/plan.png +0 -0
- package/docs/extensions/README.md +22 -24
- package/docs/extensions/board.md +361 -147
- package/docs/extensions/bytefly.md +152 -111
- package/docs/extensions/check.md +15 -17
- package/docs/extensions/context.md +35 -15
- package/docs/extensions/file-browse.md +30 -31
- package/docs/extensions/file-open.md +9 -11
- package/docs/extensions/file-read.md +12 -14
- package/docs/extensions/goal.md +15 -17
- package/docs/extensions/job.md +54 -42
- package/docs/extensions/memory.md +17 -19
- package/docs/extensions/plan.md +166 -126
- package/docs/extensions/question.md +16 -18
- package/docs/extensions/rewind.md +17 -19
- package/docs/extensions/serve.md +34 -18
- package/docs/extensions/session-bus.md +38 -16
- package/docs/extensions/subagent.md +23 -25
- package/docs/extensions/team.md +72 -33
- package/docs/extensions/todo.md +18 -18
- package/docs/extensions/watch.md +31 -31
- package/docs/extensions/web-access.md +2 -4
- package/docs/extensions/wechat.md +34 -35
- package/docs/extensions/worktree.md +56 -50
- package/extensions/board/commands.ts +56 -15
- package/extensions/board/format.ts +43 -24
- package/extensions/board/index.ts +5 -4
- package/extensions/board/input.ts +4 -9
- package/extensions/board/join.ts +4 -40
- package/extensions/board/lazy-page.ts +40 -0
- package/extensions/board/page.ts +13 -11
- package/extensions/board/result.ts +30 -16
- package/extensions/board/rows.ts +62 -25
- package/extensions/board/schema.ts +42 -10
- package/extensions/board/snapshot.ts +2 -1
- package/extensions/board/tone.ts +22 -0
- package/extensions/board/tools.ts +131 -44
- package/extensions/board/types.ts +36 -32
- package/extensions/board/view/card.ts +229 -0
- package/extensions/board/view/client.ts +33 -15
- package/extensions/board/view/dialog.ts +169 -6
- package/extensions/board/view/empty.ts +47 -0
- package/extensions/board/view/keys.ts +13 -2
- package/extensions/board/view/live.ts +89 -21
- package/extensions/board/view/names.ts +13 -4
- package/extensions/board/view/page.ts +23 -9
- package/extensions/board/view/render.ts +208 -271
- package/extensions/board/view/styles.ts +123 -31
- package/extensions/board/view/team.ts +297 -76
- package/extensions/bytefly/block/fallback.ts +1 -1
- package/extensions/bytefly/doctor/runtime.ts +5 -2
- package/extensions/bytefly/footer/collect/label.ts +60 -0
- package/extensions/bytefly/footer/collect/snapshot.ts +8 -1
- package/extensions/bytefly/footer/config.ts +4 -2
- package/extensions/bytefly/footer/register.ts +33 -4
- package/extensions/bytefly/footer/render/lines.ts +7 -4
- package/extensions/bytefly/footer/render/segments.ts +37 -10
- package/extensions/bytefly/footer/render/status.ts +0 -11
- package/extensions/bytefly/footer/types.ts +7 -0
- package/extensions/bytefly/header/config.ts +1 -1
- package/extensions/bytefly/index.ts +32 -6
- package/extensions/bytefly/mode/editor.ts +115 -0
- package/extensions/bytefly/panel/commands.ts +210 -120
- package/extensions/bytefly/panel/format.ts +4 -4
- package/extensions/bytefly/panel/settings.ts +73 -6
- package/extensions/bytefly/panel/tui/keys.ts +2 -6
- package/extensions/bytefly/update/cache.ts +1 -1
- package/extensions/bytefly/update/register.ts +4 -4
- package/extensions/bytefly/working/config.ts +5 -7
- package/extensions/bytefly/working/format.ts +10 -13
- package/extensions/bytefly/working/register.ts +22 -27
- package/extensions/check/commands.ts +3 -2
- package/extensions/check/{tui.ts → view/check-screens.ts} +14 -19
- package/extensions/context/commands.ts +2 -2
- package/extensions/context/{tui.ts → view/context-report.ts} +51 -19
- package/extensions/file-browse/index.ts +67 -36
- package/extensions/file-read/render.ts +4 -4
- package/extensions/goal/plan-route.ts +2 -2
- package/extensions/job/child.ts +527 -0
- package/extensions/job/clock.ts +142 -0
- package/extensions/job/commands.ts +4 -2
- package/extensions/job/config.ts +8 -1
- package/extensions/job/format.ts +22 -1
- package/extensions/job/log-writer.ts +13 -2
- package/extensions/job/registry.ts +63 -7
- package/extensions/job/render.ts +34 -0
- package/extensions/job/runtime.ts +296 -655
- package/extensions/job/session.ts +132 -19
- package/extensions/job/store.ts +7 -7
- package/extensions/job/tools.ts +3 -3
- package/extensions/job/types.ts +47 -0
- package/extensions/job/{tui.ts → view/jobs-screen.ts} +19 -73
- package/extensions/job/waiters.ts +44 -1
- package/extensions/memory/commands.ts +4 -2
- package/extensions/memory/{tui.ts → view/memory-picker.ts} +12 -12
- package/extensions/plan/commands.ts +12 -9
- package/extensions/plan/format.ts +8 -2
- package/extensions/plan/git-bash.ts +115 -16
- package/extensions/plan/index.ts +53 -52
- package/extensions/plan/plan-index.ts +4 -2
- package/extensions/plan/plans.ts +5 -54
- package/extensions/plan/policy.ts +8 -10
- package/extensions/plan/review-lazy.ts +85 -0
- package/extensions/plan/review.ts +2 -2
- package/extensions/plan/runtime.ts +49 -39
- package/extensions/plan/sections.ts +1 -1
- package/extensions/plan/steps.ts +3 -3
- package/extensions/plan/todos.ts +1 -1
- package/extensions/plan/tools/cancel.ts +27 -62
- package/extensions/plan/tools/enter.ts +55 -81
- package/extensions/plan/tools/exit.ts +221 -238
- package/extensions/plan/tools/refusal.ts +18 -0
- package/extensions/plan/tools/steps.ts +75 -92
- package/extensions/plan/tools/write.ts +77 -120
- package/extensions/plan/tools.ts +188 -30
- package/extensions/plan/tui.ts +5 -5
- package/extensions/plan/types.ts +48 -5
- package/extensions/plan/web-client.ts +3 -0
- package/extensions/plan/web-lazy.ts +53 -0
- package/extensions/plan/web-markdown.ts +9 -67
- package/extensions/plan/web-payload.ts +3 -3
- package/extensions/plan/web-router.ts +18 -9
- package/extensions/plan/web.ts +1 -12
- package/extensions/question/tools.ts +6 -2
- package/extensions/question/{tui.ts → view/question-screen.ts} +11 -11
- package/extensions/rewind/commands/commands.ts +6 -3
- package/extensions/rewind/state/runtime.ts +1 -1
- package/extensions/rewind/{view/status.ts → status.ts} +4 -4
- package/extensions/rewind/view/review-tui.ts +4 -4
- package/extensions/serve/config.ts +10 -8
- package/extensions/serve/index.ts +17 -3
- package/extensions/serve/registry.ts +26 -17
- package/extensions/session-bus/commands.ts +11 -6
- package/extensions/session-bus/join-request.ts +2 -1
- package/extensions/session-bus/mail-watch.ts +26 -17
- package/extensions/session-bus/protocol.ts +15 -3
- package/extensions/session-bus/resolve.ts +5 -7
- package/extensions/session-bus/runtime.ts +40 -12
- package/extensions/session-bus/store.ts +101 -19
- package/extensions/session-bus/types.ts +19 -0
- package/extensions/session-bus/{tui.ts → view/session-list.ts} +16 -16
- package/extensions/subagent/agents.ts +1 -1
- package/extensions/subagent/commands.ts +4 -2
- package/extensions/subagent/format.ts +15 -15
- package/extensions/subagent/index.ts +1 -1
- package/extensions/subagent/render.ts +3 -3
- package/extensions/subagent/{background-tui.ts → view/agents-board.ts} +11 -11
- package/extensions/team/commands.ts +24 -7
- package/extensions/team/dispatch.ts +18 -4
- package/extensions/team/format.ts +17 -2
- package/extensions/team/index.ts +9 -8
- package/extensions/team/schema.ts +6 -5
- package/extensions/team/tools.ts +107 -45
- package/extensions/team/types.ts +3 -2
- package/extensions/todo/commands.ts +4 -2
- package/extensions/todo/format.ts +11 -0
- package/extensions/todo/render.ts +57 -0
- package/extensions/todo/runtime.ts +1 -1
- package/extensions/todo/tools.ts +1 -1
- package/extensions/todo/view/todo-screen.ts +122 -0
- package/extensions/todo/widget.ts +47 -0
- package/extensions/watch/commands.ts +4 -2
- package/extensions/watch/format.ts +36 -7
- package/extensions/watch/render.ts +57 -0
- package/extensions/watch/runtime.ts +27 -22
- package/extensions/watch/tools.ts +4 -4
- package/extensions/watch/{tui.ts → view/watch-screen.ts} +18 -80
- package/extensions/web-access/fetch/tool.ts +12 -4
- package/extensions/wechat/commands/commands.ts +18 -14
- package/extensions/wechat/index.ts +72 -37
- package/extensions/wechat/state/credentials.ts +1 -1
- package/extensions/wechat/state/state.ts +1 -1
- package/extensions/wechat/text/status.ts +112 -0
- package/extensions/wechat/types.ts +2 -2
- package/extensions/wechat/view/status-screen.ts +4 -103
- package/extensions/worktree/commands.ts +11 -9
- package/extensions/worktree/enter.ts +2 -2
- package/extensions/worktree/exit.ts +2 -2
- package/extensions/worktree/index.ts +5 -5
- package/extensions/worktree/screen.ts +3 -3
- package/extensions/worktree/status.ts +2 -2
- package/extensions/worktree/tools.ts +113 -116
- package/lib/README.md +27 -13
- package/lib/board/actions.ts +111 -0
- package/lib/board/artifact.ts +149 -0
- package/lib/board/card.ts +163 -52
- package/lib/board/config.ts +58 -0
- package/lib/board/contract.ts +113 -0
- package/lib/board/join.ts +38 -0
- package/lib/board/lanes.ts +182 -0
- package/lib/board/lead.ts +130 -0
- package/lib/board/limits.ts +78 -0
- package/lib/board/links.ts +31 -10
- package/lib/board/page-pointer.ts +1 -1
- package/lib/board/read.ts +83 -0
- package/lib/board/reason.ts +102 -0
- package/lib/board/round-text.ts +68 -6
- package/lib/board/round.ts +31 -15
- package/lib/board/rules.ts +151 -307
- package/lib/board/seat.ts +35 -0
- package/lib/board/session.ts +136 -54
- package/lib/board/skipped.ts +22 -0
- package/lib/board/steps.ts +487 -0
- package/lib/board/store.ts +87 -30
- package/lib/board/tone.ts +92 -0
- package/lib/board/view.ts +70 -58
- package/{extensions/watch → lib}/child.ts +40 -21
- package/lib/env.ts +65 -7
- package/lib/format.ts +13 -0
- package/lib/http/index.ts +14 -12
- package/lib/http/port.ts +15 -10
- package/lib/lazy.ts +45 -0
- package/lib/plan-entry.ts +39 -10
- package/lib/plans/paths.ts +82 -0
- package/lib/policy.ts +9 -6
- package/lib/report.ts +3 -2
- package/lib/requirements.ts +8 -8
- package/lib/session-label.ts +111 -5
- package/lib/session-roster.ts +43 -1
- package/lib/session-tool.ts +5 -4
- package/lib/stray-fields.ts +7 -2
- package/lib/tool-names.ts +5 -10
- package/lib/tui/README.md +23 -8
- package/lib/tui/chrome.ts +16 -15
- package/lib/tui/cursor.ts +18 -3
- package/lib/tui/glyphs.ts +9 -7
- package/lib/tui/tokens.ts +33 -2
- package/lib/tui/tool.ts +3 -3
- package/lib/web/README.md +21 -0
- package/lib/web/components.ts +5 -1
- package/lib/web/index.ts +1 -0
- package/lib/web/markdown.ts +83 -0
- package/lib/web/markup.ts +2 -1
- package/lib/web/runtime.ts +9 -10
- package/package.json +6 -1
- package/skills/init/SKILL.md +5 -5
- package/skills/next/SKILL.md +3 -5
- package/extensions/board/seat.ts +0 -28
- package/extensions/todo/tui.ts +0 -212
- package/lib/tui/index.ts +0 -34
- package/skills/project-docs/SKILL.md +0 -133
- package/skills/project-docs/references/audit.md +0 -131
- package/skills/project-docs/references/changelog.md +0 -105
- package/skills/project-docs/references/discovery.md +0 -127
- package/skills/project-docs/references/readme.md +0 -80
- package/skills/project-docs/references/release.md +0 -84
- package/skills/project-docs/references/roadmap.md +0 -93
- package/skills/project-docs/scripts/state.ts +0 -316
package/extensions/job/config.ts
CHANGED
|
@@ -27,7 +27,14 @@ export interface JobsConfig {
|
|
|
27
27
|
killGraceMs: number;
|
|
28
28
|
/** Status-chip refresh interval while jobs run. */
|
|
29
29
|
repaintMs: number;
|
|
30
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* How old a session's heartbeat may be before its pid is re-checked against the process
|
|
32
|
+
* it named.
|
|
33
|
+
*
|
|
34
|
+
* The heartbeat only ticks while a job runs, so age alone means the session is idle, not
|
|
35
|
+
* gone: a quiet session keeps its jobs. The token check is what catches a pid that has
|
|
36
|
+
* since been reused by another program.
|
|
37
|
+
*/
|
|
31
38
|
sessionTtlMs: number;
|
|
32
39
|
/** Override for the registry directory; defaults under the agent dir. */
|
|
33
40
|
registryDir: string | undefined;
|
package/extensions/job/format.ts
CHANGED
|
@@ -16,7 +16,7 @@ import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
|
16
16
|
import { boundedTail, formatDuration, sanitizeUntrustedLine } from "../../lib/format.ts";
|
|
17
17
|
import { clip, clipLabel, LABEL_WIDTH } from "../../lib/tui/columns.ts";
|
|
18
18
|
import { GLYPHS, SEPARATORS } from "../../lib/tui/glyphs.ts";
|
|
19
|
-
import { byRunningFirst } from "../../lib/tui/rows.ts";
|
|
19
|
+
import { byRunningFirst, statusRow, type StatusRow } from "../../lib/tui/rows.ts";
|
|
20
20
|
import { paint, type TuiRole } from "../../lib/tui/tokens.ts";
|
|
21
21
|
import type { JobRecord, JobStatus } from "./types.ts";
|
|
22
22
|
|
|
@@ -74,6 +74,27 @@ export function shortLabel(job: JobRecord): string {
|
|
|
74
74
|
return clipLabel(job.label || job.command);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/** One row for the `/jobs` screen and its transcript mirror: selection marker,
|
|
78
|
+
* status glyph, id, label, and a right-aligned elapsed value, tagged `peer`
|
|
79
|
+
* when another session owns it. `statusRow` owns the clipping and alignment. */
|
|
80
|
+
export function jobRow(
|
|
81
|
+
job: JobRecord,
|
|
82
|
+
theme: Theme,
|
|
83
|
+
width: number,
|
|
84
|
+
options: Pick<StatusRow, "selected" | "marker"> & { foreign?: boolean } = {},
|
|
85
|
+
): string {
|
|
86
|
+
const elapsed = formatDuration(elapsedMs(job, Date.now()));
|
|
87
|
+
return statusRow(theme, width, {
|
|
88
|
+
...options,
|
|
89
|
+
glyph: statusGlyphChar(job.status),
|
|
90
|
+
glyphRole: statusRole(job.status),
|
|
91
|
+
label: `${job.id} ${shortLabel(job)}`,
|
|
92
|
+
labelRole: options.selected ? "accent" : "label",
|
|
93
|
+
// The tag rides the right-aligned cell, which survives a narrow terminal.
|
|
94
|
+
trailing: options.foreign ? `${elapsed}${SEPARATORS.item}peer` : elapsed,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
77
98
|
/** One-line job summary shared by the model output and the `/jobs` screen. */
|
|
78
99
|
function jobSummary(job: JobRecord, now: number, ownSessionId?: string): string {
|
|
79
100
|
const parts = [`${job.id}`, statusWord(job), formatDuration(elapsedMs(job, now))];
|
|
@@ -6,10 +6,14 @@
|
|
|
6
6
|
* plumbing can be read separately. The writer owns no job state: every path and
|
|
7
7
|
* limit is a callback over the runtime's live config, and a buffered line is
|
|
8
8
|
* handed back through `onLine`.
|
|
9
|
+
*
|
|
10
|
+
* The line splitter is a seam rather than an import: `lib/lines.ts` is loaded with
|
|
11
|
+
* the process seam on the first job, so a session that never starts one never
|
|
12
|
+
* loads it.
|
|
9
13
|
*/
|
|
10
14
|
|
|
11
15
|
import { createWriteStream, existsSync, renameSync, unlinkSync, type WriteStream } from "node:fs";
|
|
12
|
-
import { LineSplitter } from "../../lib/lines.ts";
|
|
16
|
+
import type { LineSplitter } from "../../lib/lines.ts";
|
|
13
17
|
import type { Job, JobRecord } from "./types.ts";
|
|
14
18
|
|
|
15
19
|
/** Bytes held while a rotation swaps the log stream before writes resume. */
|
|
@@ -36,6 +40,13 @@ export interface LogHandle {
|
|
|
36
40
|
export interface LogWriterOptions {
|
|
37
41
|
/** The clock the repaint window is measured on. */
|
|
38
42
|
now(): number;
|
|
43
|
+
/**
|
|
44
|
+
* A fresh line splitter for one job's stream.
|
|
45
|
+
*
|
|
46
|
+
* Injected rather than imported: the splitter is the only piece of `lib/lines.ts`
|
|
47
|
+
* a writer needs, and a runtime that never starts a job must not load it.
|
|
48
|
+
*/
|
|
49
|
+
newSplitter(): LineSplitter;
|
|
39
50
|
/** The live segment for a job, or undefined when it cannot be used. */
|
|
40
51
|
logPath(job: JobRecord): string | undefined;
|
|
41
52
|
/** The rotated segment for a job, or undefined when it cannot be used. */
|
|
@@ -163,7 +174,7 @@ export function createLogWriter(options: LogWriterOptions): LogWriter {
|
|
|
163
174
|
stream?.on("error", () => {});
|
|
164
175
|
return {
|
|
165
176
|
stream,
|
|
166
|
-
lines:
|
|
177
|
+
lines: options.newSplitter(),
|
|
167
178
|
queue: [],
|
|
168
179
|
queuedBytes: 0,
|
|
169
180
|
rotating: false,
|
|
@@ -22,6 +22,7 @@ import { createHash } from "node:crypto";
|
|
|
22
22
|
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
23
23
|
import { join, resolve } from "node:path";
|
|
24
24
|
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
25
|
+
import type { RosterState } from "../../lib/session-roster.ts";
|
|
25
26
|
import { registryPathFor } from "./paths.ts";
|
|
26
27
|
import { JOB_STATUSES, type JobRecord, type JobStatus, type RegistryFile } from "./types.ts";
|
|
27
28
|
|
|
@@ -203,6 +204,59 @@ export function settleGone(record: JobRecord, options: SettleGoneOptions): JobRe
|
|
|
203
204
|
return { ...record, status, exitCode: code, finishedAt: options.now };
|
|
204
205
|
}
|
|
205
206
|
|
|
207
|
+
/** What a load makes of every session's file, before the runtime touches a record. */
|
|
208
|
+
export interface LoadedRecords {
|
|
209
|
+
/** Every record, merged across the session files and reconciled against liveness. */
|
|
210
|
+
records: JobRecord[];
|
|
211
|
+
/** Live, non-detached leftovers for the caller to kill. */
|
|
212
|
+
orphans: JobRecord[];
|
|
213
|
+
/** Sessions whose file may be dropped once their records are rewritten here. */
|
|
214
|
+
deadSessions: Set<string>;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** The liveness and ownership seams a load reconciles against. */
|
|
218
|
+
export interface LoadSeams {
|
|
219
|
+
/** This session, which adopts a dead one's records. */
|
|
220
|
+
sessionId: string;
|
|
221
|
+
/** What the session that wrote a file is now. */
|
|
222
|
+
ownerState: (sessionId: string) => RosterState;
|
|
223
|
+
/** The process seams: whether a pid runs, whether its token still matches, its exit code. */
|
|
224
|
+
process: {
|
|
225
|
+
alive: (pid: number) => boolean;
|
|
226
|
+
owns: (record: JobRecord) => boolean;
|
|
227
|
+
exitCode: (record: JobRecord) => number | undefined;
|
|
228
|
+
};
|
|
229
|
+
now: number;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** Merge every session's file, recover dead pids, and classify the survivors. */
|
|
233
|
+
export function loadRecords(files: readonly RegistryFile[], seams: LoadSeams): LoadedRecords {
|
|
234
|
+
const merged = new Map<string, JobRecord>();
|
|
235
|
+
const deadSessions = new Set<string>();
|
|
236
|
+
for (const file of files) {
|
|
237
|
+
if (file.sessionId !== seams.sessionId && seams.ownerState(file.sessionId) === "gone")
|
|
238
|
+
deadSessions.add(file.sessionId);
|
|
239
|
+
for (const record of file.jobs) {
|
|
240
|
+
const existing = merged.get(record.id);
|
|
241
|
+
merged.set(record.id, existing ? mergeRecords(existing, record, seams.sessionId) : record);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// Resolve dead pids (recovering exit codes), then classify the survivors.
|
|
245
|
+
const settled = [...merged.values()].map((record) =>
|
|
246
|
+
settleGone(record, {
|
|
247
|
+
isAlive: seams.process.alive,
|
|
248
|
+
tokenMatches: seams.process.owns,
|
|
249
|
+
readExitCode: seams.process.exitCode,
|
|
250
|
+
now: seams.now,
|
|
251
|
+
}),
|
|
252
|
+
);
|
|
253
|
+
const { jobs, orphans } = planReconcile(settled, seams.process.alive, seams.now, {
|
|
254
|
+
ownerState: seams.ownerState,
|
|
255
|
+
currentSessionId: seams.sessionId,
|
|
256
|
+
});
|
|
257
|
+
return { records: jobs, orphans, deadSessions };
|
|
258
|
+
}
|
|
259
|
+
|
|
206
260
|
export interface ReconcileResult {
|
|
207
261
|
/** The records after liveness reconciliation. */
|
|
208
262
|
jobs: JobRecord[];
|
|
@@ -213,10 +267,12 @@ export interface ReconcileResult {
|
|
|
213
267
|
/** Owner-liveness context for {@link planReconcile}. */
|
|
214
268
|
export interface ReconcileOptions {
|
|
215
269
|
/**
|
|
216
|
-
*
|
|
217
|
-
*
|
|
270
|
+
* What the session that started a job is: `live`, `quiet`, or `gone`.
|
|
271
|
+
*
|
|
272
|
+
* Only `gone` frees the job to be reaped. A `quiet` owner is an idle one — its
|
|
273
|
+
* heartbeat stops while it has nothing running — and its job is still its own.
|
|
218
274
|
*/
|
|
219
|
-
|
|
275
|
+
ownerState?: (sessionId: string) => RosterState;
|
|
220
276
|
/** The reconciling session; its own leftovers are always reaped. */
|
|
221
277
|
currentSessionId?: string;
|
|
222
278
|
}
|
|
@@ -250,12 +306,12 @@ export function planReconcile(
|
|
|
250
306
|
jobs.push(record);
|
|
251
307
|
continue;
|
|
252
308
|
}
|
|
253
|
-
// Another
|
|
254
|
-
//
|
|
309
|
+
// Another session still owns this job: keep it running instead of reaping a
|
|
310
|
+
// peer's work. Its owner is only `gone` when its process is.
|
|
255
311
|
if (
|
|
256
|
-
options.
|
|
312
|
+
options.ownerState &&
|
|
257
313
|
record.sessionId !== options.currentSessionId &&
|
|
258
|
-
options.
|
|
314
|
+
options.ownerState(record.sessionId) !== "gone"
|
|
259
315
|
) {
|
|
260
316
|
jobs.push(record);
|
|
261
317
|
continue;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `JobResult` transcript block: the `job` tool's list-or-log-tail result.
|
|
3
|
+
*
|
|
4
|
+
* It maps the job vocabulary onto the shared `TailResult` kit, so the tool's
|
|
5
|
+
* `renderResult` stays a few lines and every row is drawn by `jobRow` in
|
|
6
|
+
* `format.ts`. The `/jobs` screen draws the same rows through the same helper,
|
|
7
|
+
* which is why it lives beside the pure format helpers rather than here: this
|
|
8
|
+
* module is on the registration path, and the screen is not.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { TailResultInput } from "../../lib/tui/tool.ts";
|
|
12
|
+
import { jobRow } from "./format.ts";
|
|
13
|
+
import type { JobRecord } from "./types.ts";
|
|
14
|
+
|
|
15
|
+
/** Input for the transcript result: a themed job list or a log tail. */
|
|
16
|
+
export type JobResultInput =
|
|
17
|
+
| { kind: "list"; jobs: JobRecord[]; more: number; sessionId?: string }
|
|
18
|
+
| { kind: "logs"; lines: string[]; earlier: number };
|
|
19
|
+
|
|
20
|
+
/** Map the job vocabulary onto the shared transcript tail block. */
|
|
21
|
+
export function jobTail(input: JobResultInput): TailResultInput<JobRecord> {
|
|
22
|
+
if (input.kind === "logs") {
|
|
23
|
+
return { kind: "lines", lines: input.lines, earlier: input.earlier, earlierLabel: "lines" };
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
kind: "list",
|
|
27
|
+
rows: input.jobs,
|
|
28
|
+
more: input.more,
|
|
29
|
+
rowLine: (job, width, theme) => {
|
|
30
|
+
const foreign = input.sessionId !== undefined && job.sessionId !== input.sessionId;
|
|
31
|
+
return jobRow(job, theme, width, { marker: false, foreign });
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|