@h-rig/cli 0.0.6-alpha.9 → 0.0.6-alpha.90
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 +1 -1
- package/dist/bin/build-rig-binaries.d.ts +2 -0
- package/dist/bin/rig.d.ts +2 -0
- package/dist/bin/rig.js +11052 -6668
- package/dist/src/app/board.d.ts +23 -0
- package/dist/src/app/board.js +1786 -0
- package/dist/src/app/drone-ui.d.ts +37 -0
- package/dist/src/app/drone-ui.js +294 -0
- package/dist/src/app/theme.d.ts +47 -0
- package/dist/src/app/theme.js +150 -0
- package/dist/src/commands/_async-ui.d.ts +13 -0
- package/dist/src/commands/_async-ui.js +223 -0
- package/dist/src/commands/_authority-runs.d.ts +22 -0
- package/dist/src/commands/_authority-runs.js +2 -3
- package/dist/src/commands/_cli-format.d.ts +49 -0
- package/dist/src/commands/_cli-format.js +447 -0
- package/dist/src/commands/_connection-state.d.ts +44 -0
- package/dist/src/commands/_connection-state.js +30 -11
- package/dist/src/commands/_doctor-checks.d.ts +52 -0
- package/dist/src/commands/_doctor-checks.js +180 -44
- package/dist/src/commands/_help-catalog.d.ts +51 -0
- package/dist/src/commands/_help-catalog.js +442 -0
- package/dist/src/commands/_json-output.d.ts +11 -0
- package/dist/src/commands/_json-output.js +56 -0
- package/dist/src/commands/_operator-surface.d.ts +34 -0
- package/dist/src/commands/_operator-surface.js +220 -0
- package/dist/src/commands/_operator-view.d.ts +30 -0
- package/dist/src/commands/_operator-view.js +803 -73
- package/dist/src/commands/_parsers.d.ts +15 -0
- package/dist/src/commands/_parsers.js +18 -11
- package/dist/src/commands/_paths.d.ts +11 -0
- package/dist/src/commands/_pi-frontend.d.ts +27 -0
- package/dist/src/commands/_pi-frontend.js +742 -0
- package/dist/src/commands/_pi-install.d.ts +42 -0
- package/dist/src/commands/_pi-install.js +5 -4
- package/dist/src/commands/_policy.d.ts +8 -0
- package/dist/src/commands/_policy.js +12 -5
- package/dist/src/commands/_preflight.d.ts +22 -0
- package/dist/src/commands/_preflight.js +190 -128
- package/dist/src/commands/_probes.d.ts +1 -0
- package/dist/src/commands/_run-driver-helpers.d.ts +99 -0
- package/dist/src/commands/_run-driver-helpers.js +75 -22
- package/dist/src/commands/_run-replay.d.ts +24 -0
- package/dist/src/commands/_run-replay.js +142 -0
- package/dist/src/commands/_server-client.d.ts +186 -0
- package/dist/src/commands/_server-client.js +360 -61
- package/dist/src/commands/_snapshot-upload.d.ts +39 -0
- package/dist/src/commands/_snapshot-upload.js +163 -39
- package/dist/src/commands/_spinner.d.ts +25 -0
- package/dist/src/commands/_spinner.js +65 -0
- package/dist/src/commands/_task-picker.d.ts +9 -0
- package/dist/src/commands/_task-picker.js +172 -19
- package/dist/src/commands/agent.d.ts +3 -0
- package/dist/src/commands/agent.js +39 -20
- package/dist/src/commands/browser.d.ts +65 -0
- package/dist/src/commands/browser.js +334 -51
- package/dist/src/commands/connect.d.ts +7 -0
- package/dist/src/commands/connect.js +272 -33
- package/dist/src/commands/dist.d.ts +28 -0
- package/dist/src/commands/dist.js +19 -12
- package/dist/src/commands/doctor.d.ts +3 -0
- package/dist/src/commands/doctor.js +378 -45
- package/dist/src/commands/github.d.ts +3 -0
- package/dist/src/commands/github.js +375 -53
- package/dist/src/commands/inbox.d.ts +30 -0
- package/dist/src/commands/inbox.js +760 -70
- package/dist/src/commands/init.d.ts +74 -0
- package/dist/src/commands/init.js +963 -119
- package/dist/src/commands/inspect.d.ts +3 -0
- package/dist/src/commands/inspect.js +588 -32
- package/dist/src/commands/inspector.d.ts +3 -0
- package/dist/src/commands/inspector.js +20 -13
- package/dist/src/commands/pi.d.ts +3 -0
- package/dist/src/commands/pi.js +177 -0
- package/dist/src/commands/plugin.d.ts +16 -0
- package/dist/src/commands/plugin.js +95 -27
- package/dist/src/commands/profile-and-review.d.ts +4 -0
- package/dist/src/commands/profile-and-review.js +26 -19
- package/dist/src/commands/queue.d.ts +3 -0
- package/dist/src/commands/queue.js +32 -12
- package/dist/src/commands/remote.d.ts +3 -0
- package/dist/src/commands/remote.js +43 -36
- package/dist/src/commands/repo-git-harness.d.ts +5 -0
- package/dist/src/commands/repo-git-harness.js +22 -15
- package/dist/src/commands/run.d.ts +3 -0
- package/dist/src/commands/run.js +1379 -159
- package/dist/src/commands/server.d.ts +7 -0
- package/dist/src/commands/server.js +502 -57
- package/dist/src/commands/setup.d.ts +16 -0
- package/dist/src/commands/setup.js +390 -63
- package/dist/src/commands/stats.d.ts +12 -0
- package/dist/src/commands/stats.js +1051 -0
- package/dist/src/commands/task-report-bug.d.ts +19 -0
- package/dist/src/commands/task-report-bug.js +260 -62
- package/dist/src/commands/task-run-driver.d.ts +132 -0
- package/dist/src/commands/task-run-driver.js +886 -130
- package/dist/src/commands/task.d.ts +14 -0
- package/dist/src/commands/task.js +1644 -314
- package/dist/src/commands/test.d.ts +3 -0
- package/dist/src/commands/test.js +15 -8
- package/dist/src/commands/workspace.d.ts +3 -0
- package/dist/src/commands/workspace.js +18 -11
- package/dist/src/commands.d.ts +29 -0
- package/dist/src/commands.js +10967 -6637
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +10168 -5787
- package/dist/src/launcher.d.ts +61 -0
- package/dist/src/launcher.js +77 -13
- package/dist/src/report-bug.d.ts +44 -0
- package/dist/src/report-bug.js +3 -3
- package/dist/src/runner.d.ts +47 -0
- package/dist/src/runner.js +16 -22
- package/dist/src/withMutedConsole.d.ts +2 -0
- package/package.json +13 -6
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { type AuthorityRunPatch, type AuthorityRunRecord } from "@rig/runtime/control-plane/authority-files";
|
|
2
|
+
import type { RunStatus } from "@rig/contracts";
|
|
3
|
+
export type SourceTaskContract = {
|
|
4
|
+
id: string;
|
|
5
|
+
title?: string | null;
|
|
6
|
+
description?: string | null;
|
|
7
|
+
body?: string | null;
|
|
8
|
+
acceptanceCriteria?: string | null;
|
|
9
|
+
acceptance_criteria?: string | null;
|
|
10
|
+
sourceIssueId?: string | null;
|
|
11
|
+
status?: string | null;
|
|
12
|
+
issueType?: string | null;
|
|
13
|
+
role?: string | null;
|
|
14
|
+
externalRef?: string | null;
|
|
15
|
+
scope?: readonly string[];
|
|
16
|
+
validation?: readonly string[];
|
|
17
|
+
validators?: readonly string[];
|
|
18
|
+
labels?: readonly string[];
|
|
19
|
+
};
|
|
20
|
+
export declare function patchAuthorityRun(projectRoot: string, runId: string, patch: AuthorityRunPatch): AuthorityRunRecord;
|
|
21
|
+
/**
|
|
22
|
+
* THE status mutation on the CLI driver side: transition-checked and
|
|
23
|
+
* journaled as a status-changed event (see @rig/contracts run-journal).
|
|
24
|
+
*/
|
|
25
|
+
export declare function setRunStatusOrFail(projectRoot: string, runId: string, to: RunStatus, options?: {
|
|
26
|
+
reason?: string | null;
|
|
27
|
+
errorText?: string | null;
|
|
28
|
+
}): AuthorityRunRecord;
|
|
29
|
+
export declare function touchAuthorityRun(projectRoot: string, runId: string): void;
|
|
30
|
+
export declare function appendRunTimeline(projectRoot: string, runId: string, value: Record<string, unknown>): void;
|
|
31
|
+
export declare function appendRunLog(projectRoot: string, runId: string, value: Record<string, unknown>): void;
|
|
32
|
+
type RunActionInput = {
|
|
33
|
+
id: string;
|
|
34
|
+
actionType: string;
|
|
35
|
+
title: string;
|
|
36
|
+
detail?: string | null;
|
|
37
|
+
state: "running" | "completed" | "failed";
|
|
38
|
+
startedAt: string;
|
|
39
|
+
completedAt?: string | null;
|
|
40
|
+
payload?: Record<string, unknown>;
|
|
41
|
+
};
|
|
42
|
+
export declare function appendRunAction(projectRoot: string, runId: string, value: RunActionInput): void;
|
|
43
|
+
export type RunActionHandle = {
|
|
44
|
+
startedAt: string;
|
|
45
|
+
complete: (detail?: string | null, payload?: Record<string, unknown>) => void;
|
|
46
|
+
fail: (detail: string, payload?: Record<string, unknown>) => void;
|
|
47
|
+
};
|
|
48
|
+
export declare function startRunAction(projectRoot: string, runId: string, input: {
|
|
49
|
+
actionId: string;
|
|
50
|
+
actionType: string;
|
|
51
|
+
title: string;
|
|
52
|
+
detail?: string | null;
|
|
53
|
+
payload?: Record<string, unknown>;
|
|
54
|
+
}): RunActionHandle;
|
|
55
|
+
export type RunEvent = {
|
|
56
|
+
type: "status";
|
|
57
|
+
runId: string;
|
|
58
|
+
status: string;
|
|
59
|
+
detail?: string | null;
|
|
60
|
+
sessionId?: string | null;
|
|
61
|
+
} | {
|
|
62
|
+
type: "timeline";
|
|
63
|
+
runId: string;
|
|
64
|
+
} | {
|
|
65
|
+
type: "log";
|
|
66
|
+
runId: string;
|
|
67
|
+
title?: string;
|
|
68
|
+
} | {
|
|
69
|
+
type: "completed";
|
|
70
|
+
runId: string;
|
|
71
|
+
} | {
|
|
72
|
+
type: "failed";
|
|
73
|
+
runId: string;
|
|
74
|
+
error: string;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Route emitServerRunEvent through the run.jsonl lifecycle log + doorbell in
|
|
78
|
+
* addition to stdout. Called once at the start of executeRigOwnedTaskRun.
|
|
79
|
+
*/
|
|
80
|
+
export declare function configureRunEventSink(projectRoot: string): void;
|
|
81
|
+
/**
|
|
82
|
+
* Print a parseable status line to stdout that the server's spawn-and-watch
|
|
83
|
+
* path reads to update its own state. Format: `__RIG_RUN_EVENT__<json>`.
|
|
84
|
+
*
|
|
85
|
+
* When `configureRunEventSink` has run, the same event is also appended to
|
|
86
|
+
* the run's `run.jsonl` lifecycle log and the server doorbell is rung.
|
|
87
|
+
*/
|
|
88
|
+
export declare function emitServerRunEvent(event: RunEvent): void;
|
|
89
|
+
export declare function buildRunPrompt(input: {
|
|
90
|
+
projectRoot: string;
|
|
91
|
+
taskId?: string;
|
|
92
|
+
fallbackTitle?: string | null;
|
|
93
|
+
fallbackDescription?: string | null;
|
|
94
|
+
fallbackAcceptanceCriteria?: string | null;
|
|
95
|
+
sourceTask?: SourceTaskContract | null;
|
|
96
|
+
initialPrompt?: string;
|
|
97
|
+
runtimeAdapter: "claude-code" | "codex" | "pi";
|
|
98
|
+
}): string;
|
|
99
|
+
export {};
|
|
@@ -5,21 +5,33 @@ import { resolve as resolve3 } from "path";
|
|
|
5
5
|
|
|
6
6
|
// packages/cli/src/runner.ts
|
|
7
7
|
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
8
|
-
import { CliError } from "@rig/runtime/control-plane/errors";
|
|
8
|
+
import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
|
|
9
9
|
import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
|
|
10
|
-
import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
|
|
11
|
-
import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
|
|
12
10
|
import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
|
|
13
|
-
|
|
11
|
+
|
|
12
|
+
class CliError extends RuntimeCliError {
|
|
13
|
+
hint;
|
|
14
|
+
constructor(message, exitCode = 1, options = {}) {
|
|
15
|
+
super(message, exitCode);
|
|
16
|
+
if (options.hint?.trim()) {
|
|
17
|
+
this.hint = options.hint.trim();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
14
21
|
|
|
15
22
|
// packages/cli/src/commands/_run-driver-helpers.ts
|
|
16
23
|
import {
|
|
17
|
-
|
|
24
|
+
appendRunJournalEvent,
|
|
25
|
+
appendRunLogEntry,
|
|
26
|
+
appendRunTimelineEntry,
|
|
27
|
+
patchAuthorityRunRecord,
|
|
18
28
|
readAuthorityRun as readAuthorityRun2,
|
|
19
|
-
resolveAuthorityRunDir
|
|
20
|
-
|
|
29
|
+
resolveAuthorityRunDir,
|
|
30
|
+
setAuthorityRunStatus,
|
|
31
|
+
writeJsonFile
|
|
21
32
|
} from "@rig/runtime/control-plane/authority-files";
|
|
22
33
|
import { taskLookup } from "@rig/runtime/control-plane/native/task-ops";
|
|
34
|
+
import { readPriorPrProgressPromptSection } from "@rig/runtime/control-plane/prompt-context";
|
|
23
35
|
import { buildProviderTaskRunInstructionLines } from "@rig/runtime/control-plane/provider/runtime-instructions";
|
|
24
36
|
import { loadRigTaskRunSkillBody } from "@rig/runtime/control-plane/provider/rig-task-run-skill";
|
|
25
37
|
|
|
@@ -29,8 +41,7 @@ import { resolve as resolve2 } from "path";
|
|
|
29
41
|
import {
|
|
30
42
|
readAuthorityRun,
|
|
31
43
|
readJsonlFile,
|
|
32
|
-
|
|
33
|
-
writeJsonFile
|
|
44
|
+
writeAuthorityRunRecord
|
|
34
45
|
} from "@rig/runtime/control-plane/authority-files";
|
|
35
46
|
|
|
36
47
|
// packages/cli/src/commands/_paths.ts
|
|
@@ -64,16 +75,20 @@ function readLatestBeadRecord(projectRoot, taskId) {
|
|
|
64
75
|
|
|
65
76
|
// packages/cli/src/commands/_run-driver-helpers.ts
|
|
66
77
|
function patchAuthorityRun(projectRoot, runId, patch) {
|
|
67
|
-
const
|
|
68
|
-
if (!
|
|
69
|
-
throw new
|
|
78
|
+
const next = patchAuthorityRunRecord(projectRoot, runId, patch);
|
|
79
|
+
if (!next) {
|
|
80
|
+
throw new CliError(`Run not found: ${runId}`, 2, { hint: "Run `rig run list` to see recorded runs." });
|
|
81
|
+
}
|
|
82
|
+
return next;
|
|
83
|
+
}
|
|
84
|
+
function setRunStatusOrFail(projectRoot, runId, to, options = {}) {
|
|
85
|
+
const next = setAuthorityRunStatus(projectRoot, runId, to, {
|
|
86
|
+
...options,
|
|
87
|
+
actor: { kind: "agent" }
|
|
88
|
+
});
|
|
89
|
+
if (!next) {
|
|
90
|
+
throw new CliError(`Run not found: ${runId}`, 2, { hint: "Run `rig run list` to see recorded runs." });
|
|
70
91
|
}
|
|
71
|
-
const next = {
|
|
72
|
-
...current,
|
|
73
|
-
...patch,
|
|
74
|
-
updatedAt: new Date().toISOString()
|
|
75
|
-
};
|
|
76
|
-
writeJsonFile2(resolve3(resolveAuthorityRunDir2(projectRoot, runId), "run.json"), next);
|
|
77
92
|
return next;
|
|
78
93
|
}
|
|
79
94
|
function touchAuthorityRun(projectRoot, runId) {
|
|
@@ -81,21 +96,21 @@ function touchAuthorityRun(projectRoot, runId) {
|
|
|
81
96
|
if (!current) {
|
|
82
97
|
return;
|
|
83
98
|
}
|
|
84
|
-
|
|
99
|
+
writeJsonFile(resolve3(resolveAuthorityRunDir(projectRoot, runId), "run.json"), {
|
|
85
100
|
...current,
|
|
86
101
|
updatedAt: new Date().toISOString()
|
|
87
102
|
});
|
|
88
103
|
}
|
|
89
104
|
function appendRunTimeline(projectRoot, runId, value) {
|
|
90
|
-
|
|
105
|
+
appendRunTimelineEntry(projectRoot, runId, value);
|
|
91
106
|
touchAuthorityRun(projectRoot, runId);
|
|
92
107
|
}
|
|
93
108
|
function appendRunLog(projectRoot, runId, value) {
|
|
94
|
-
|
|
109
|
+
appendRunLogEntry(projectRoot, runId, value);
|
|
95
110
|
touchAuthorityRun(projectRoot, runId);
|
|
96
111
|
}
|
|
97
112
|
function appendRunAction(projectRoot, runId, value) {
|
|
98
|
-
|
|
113
|
+
appendRunTimelineEntry(projectRoot, runId, {
|
|
99
114
|
id: value.id,
|
|
100
115
|
type: "action",
|
|
101
116
|
actionType: value.actionType,
|
|
@@ -149,8 +164,43 @@ function startRunAction(projectRoot, runId, input) {
|
|
|
149
164
|
}
|
|
150
165
|
};
|
|
151
166
|
}
|
|
167
|
+
var runEventSinkProjectRoot = null;
|
|
168
|
+
function configureRunEventSink(projectRoot) {
|
|
169
|
+
runEventSinkProjectRoot = projectRoot;
|
|
170
|
+
}
|
|
171
|
+
var lastDoorbellRangAt = 0;
|
|
172
|
+
function ringServerRunDoorbell(runId) {
|
|
173
|
+
const serverUrl = process.env.RIG_SERVER_URL?.trim();
|
|
174
|
+
if (!serverUrl)
|
|
175
|
+
return;
|
|
176
|
+
const now = Date.now();
|
|
177
|
+
if (now - lastDoorbellRangAt < 250)
|
|
178
|
+
return;
|
|
179
|
+
lastDoorbellRangAt = now;
|
|
180
|
+
const token = process.env.RIG_AUTH_TOKEN || process.env.RIG_GITHUB_TOKEN || "";
|
|
181
|
+
fetch(`${serverUrl.replace(/\/+$/, "")}/api/runs/doorbell`, {
|
|
182
|
+
method: "POST",
|
|
183
|
+
headers: {
|
|
184
|
+
"content-type": "application/json",
|
|
185
|
+
authorization: `Bearer ${token}`
|
|
186
|
+
},
|
|
187
|
+
body: JSON.stringify({ runId }),
|
|
188
|
+
signal: AbortSignal.timeout(1000)
|
|
189
|
+
}).catch(() => {});
|
|
190
|
+
}
|
|
152
191
|
function emitServerRunEvent(event) {
|
|
153
192
|
console.log(`__RIG_RUN_EVENT__${JSON.stringify({ ...event, at: new Date().toISOString() })}`);
|
|
193
|
+
if (runEventSinkProjectRoot) {
|
|
194
|
+
try {
|
|
195
|
+
if (event.type === "status" || event.type === "completed" || event.type === "failed") {
|
|
196
|
+
appendRunJournalEvent(runEventSinkProjectRoot, event.runId, {
|
|
197
|
+
type: "timeline-entry",
|
|
198
|
+
payload: { kind: "driver-event", ...event }
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
} catch {}
|
|
202
|
+
ringServerRunDoorbell(event.runId);
|
|
203
|
+
}
|
|
154
204
|
}
|
|
155
205
|
function buildRunPrompt(input) {
|
|
156
206
|
const initialPrompt = input.initialPrompt?.trim() || null;
|
|
@@ -207,6 +257,7 @@ ${acceptance}` : null,
|
|
|
207
257
|
${sourceContractLines.join(`
|
|
208
258
|
`)}` : null,
|
|
209
259
|
scopeText || renderSourceScopeValidation(sourceTask, sourceValidation) || null,
|
|
260
|
+
readPriorPrProgressPromptSection(input.projectRoot, input.taskId),
|
|
210
261
|
initialPrompt ? `Additional operator guidance:
|
|
211
262
|
${initialPrompt}` : null,
|
|
212
263
|
providerLines.length > 0 ? `Provider-specific runtime tooling:
|
|
@@ -280,8 +331,10 @@ function renderSourceScopeValidation(task, validation) {
|
|
|
280
331
|
export {
|
|
281
332
|
touchAuthorityRun,
|
|
282
333
|
startRunAction,
|
|
334
|
+
setRunStatusOrFail,
|
|
283
335
|
patchAuthorityRun,
|
|
284
336
|
emitServerRunEvent,
|
|
337
|
+
configureRunEventSink,
|
|
285
338
|
buildRunPrompt,
|
|
286
339
|
appendRunTimeline,
|
|
287
340
|
appendRunLog,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type AuthorityRunRecord } from "@rig/runtime/control-plane/authority-files";
|
|
2
|
+
export type RunReplayLine = {
|
|
3
|
+
at: string | null;
|
|
4
|
+
source: "run" | "session";
|
|
5
|
+
summary: string;
|
|
6
|
+
};
|
|
7
|
+
export type RunReplayResult = {
|
|
8
|
+
runId: string;
|
|
9
|
+
logPath: string;
|
|
10
|
+
sessionFile: string | null;
|
|
11
|
+
entryCount: number;
|
|
12
|
+
sessionEntryCount: number;
|
|
13
|
+
lines: string[];
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Locate the worker Pi session.jsonl for a run, without ever reading the file
|
|
17
|
+
* during the run lifecycle — replay-time only. Prefers the exact
|
|
18
|
+
* piSession.sessionFile recorded on the run record; falls back to scanning
|
|
19
|
+
* `<piSession.cwd>/.rig/session/` for `*_<sessionId>.jsonl`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveRunSessionFile(record: AuthorityRunRecord | null): string | null;
|
|
22
|
+
export declare function buildRunReplay(projectRoot: string, runId: string, options?: {
|
|
23
|
+
withSession?: boolean;
|
|
24
|
+
}): RunReplayResult;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// packages/cli/src/commands/_run-replay.ts
|
|
3
|
+
import { existsSync, readdirSync } from "fs";
|
|
4
|
+
import { join, resolve } from "path";
|
|
5
|
+
import {
|
|
6
|
+
readAuthorityRun,
|
|
7
|
+
readJsonlFile,
|
|
8
|
+
runJournalPath
|
|
9
|
+
} from "@rig/runtime/control-plane/authority-files";
|
|
10
|
+
function asRecord(value) {
|
|
11
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
12
|
+
}
|
|
13
|
+
function text(value) {
|
|
14
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
15
|
+
}
|
|
16
|
+
function snippet(value, max = 120) {
|
|
17
|
+
const raw = text(value);
|
|
18
|
+
if (!raw)
|
|
19
|
+
return null;
|
|
20
|
+
const flat = raw.replace(/\s+/g, " ");
|
|
21
|
+
return flat.length > max ? `${flat.slice(0, max - 1)}\u2026` : flat;
|
|
22
|
+
}
|
|
23
|
+
function summarizeLifecycleEntry(entry) {
|
|
24
|
+
const type = text(entry.type) ?? "event";
|
|
25
|
+
switch (type) {
|
|
26
|
+
case "status": {
|
|
27
|
+
const anchor = text(entry.sessionId);
|
|
28
|
+
return [
|
|
29
|
+
`status \u2192 ${text(entry.status) ?? "(unknown)"}`,
|
|
30
|
+
snippet(entry.detail) ? `\u2014 ${snippet(entry.detail)}` : null,
|
|
31
|
+
anchor ? `[session ${anchor}]` : null
|
|
32
|
+
].filter(Boolean).join(" ");
|
|
33
|
+
}
|
|
34
|
+
case "timeline-entry": {
|
|
35
|
+
const payload = asRecord(entry.payload) ?? {};
|
|
36
|
+
const kind = text(payload.type) ?? "entry";
|
|
37
|
+
const body = snippet(payload.title) ?? snippet(payload.text) ?? snippet(payload.detail);
|
|
38
|
+
const state = text(payload.state);
|
|
39
|
+
return [`timeline ${kind}`, body ? `\u2014 ${body}` : null, state ? `(${state})` : null].filter(Boolean).join(" ");
|
|
40
|
+
}
|
|
41
|
+
case "log-entry": {
|
|
42
|
+
const payload = asRecord(entry.payload) ?? {};
|
|
43
|
+
const title = snippet(payload.title) ?? "log";
|
|
44
|
+
const detail = snippet(payload.detail);
|
|
45
|
+
return [`log ${title}`, detail ? `\u2014 ${detail}` : null].filter(Boolean).join(" ");
|
|
46
|
+
}
|
|
47
|
+
case "record-patch": {
|
|
48
|
+
const patch = asRecord(entry.patch) ?? {};
|
|
49
|
+
const keys = Object.keys(patch);
|
|
50
|
+
const shown = keys.slice(0, 8).join(", ");
|
|
51
|
+
return `record-patch {${shown}${keys.length > 8 ? `, +${keys.length - 8} more` : ""}}`;
|
|
52
|
+
}
|
|
53
|
+
case "timeline":
|
|
54
|
+
return "timeline updated (signal)";
|
|
55
|
+
case "log":
|
|
56
|
+
return `log signal${snippet(entry.title) ? ` \u2014 ${snippet(entry.title)}` : ""}`;
|
|
57
|
+
case "completed":
|
|
58
|
+
return "run completed";
|
|
59
|
+
case "failed":
|
|
60
|
+
return `run failed${snippet(entry.error) ? ` \u2014 ${snippet(entry.error)}` : ""}`;
|
|
61
|
+
default:
|
|
62
|
+
return type;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function summarizeSessionEntry(entry) {
|
|
66
|
+
const type = text(entry.type) ?? "entry";
|
|
67
|
+
const message = asRecord(entry.message);
|
|
68
|
+
const role = text(message?.role);
|
|
69
|
+
const content = message?.content;
|
|
70
|
+
let body = null;
|
|
71
|
+
if (typeof content === "string") {
|
|
72
|
+
body = snippet(content);
|
|
73
|
+
} else if (Array.isArray(content)) {
|
|
74
|
+
body = snippet(content.map((part) => text(asRecord(part)?.text) ?? "").filter(Boolean).join(" "));
|
|
75
|
+
}
|
|
76
|
+
return [
|
|
77
|
+
`pi ${type}`,
|
|
78
|
+
role ? `(${role})` : null,
|
|
79
|
+
body ? `\u2014 ${body}` : null
|
|
80
|
+
].filter(Boolean).join(" ");
|
|
81
|
+
}
|
|
82
|
+
function sessionEntryTimestamp(entry) {
|
|
83
|
+
return text(entry.timestamp) ?? text(entry.at) ?? text(entry.createdAt) ?? null;
|
|
84
|
+
}
|
|
85
|
+
function resolveRunSessionFile(record) {
|
|
86
|
+
const piSession = record?.piSession ?? null;
|
|
87
|
+
if (!piSession)
|
|
88
|
+
return null;
|
|
89
|
+
const recorded = text(piSession.sessionFile);
|
|
90
|
+
if (recorded && existsSync(recorded)) {
|
|
91
|
+
return recorded;
|
|
92
|
+
}
|
|
93
|
+
const cwd = text(piSession.cwd);
|
|
94
|
+
const sessionId = text(piSession.sessionId);
|
|
95
|
+
if (!cwd || !sessionId)
|
|
96
|
+
return null;
|
|
97
|
+
const sessionDir = resolve(cwd, ".rig", "session");
|
|
98
|
+
try {
|
|
99
|
+
const match = readdirSync(sessionDir).find((name) => name.endsWith(`_${sessionId}.jsonl`));
|
|
100
|
+
return match ? join(sessionDir, match) : null;
|
|
101
|
+
} catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function buildRunReplay(projectRoot, runId, options = {}) {
|
|
106
|
+
const logPath = runJournalPath(projectRoot, runId);
|
|
107
|
+
const record = readAuthorityRun(projectRoot, runId);
|
|
108
|
+
const lifecycleEntries = readJsonlFile(logPath).map((entry) => asRecord(entry)).filter((entry) => entry !== null);
|
|
109
|
+
const merged = lifecycleEntries.map((entry) => ({
|
|
110
|
+
at: text(entry.at),
|
|
111
|
+
source: "run",
|
|
112
|
+
summary: summarizeLifecycleEntry(entry)
|
|
113
|
+
}));
|
|
114
|
+
let sessionFile = null;
|
|
115
|
+
let sessionEntryCount = 0;
|
|
116
|
+
if (options.withSession) {
|
|
117
|
+
sessionFile = resolveRunSessionFile(record);
|
|
118
|
+
if (sessionFile) {
|
|
119
|
+
let lastSeenAt = null;
|
|
120
|
+
const sessionLines = readJsonlFile(sessionFile).map((entry) => asRecord(entry)).filter((entry) => entry !== null).map((entry) => {
|
|
121
|
+
lastSeenAt = sessionEntryTimestamp(entry) ?? lastSeenAt;
|
|
122
|
+
return { at: lastSeenAt, source: "session", summary: summarizeSessionEntry(entry) };
|
|
123
|
+
});
|
|
124
|
+
sessionEntryCount = sessionLines.length;
|
|
125
|
+
merged.push(...sessionLines);
|
|
126
|
+
merged.sort((left, right) => (left.at ?? "").localeCompare(right.at ?? ""));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const lines = merged.map((line) => `${line.at ?? "(no timestamp) "} ${line.source === "run" ? "run " : "session"} ${line.summary}`);
|
|
130
|
+
return {
|
|
131
|
+
runId,
|
|
132
|
+
logPath,
|
|
133
|
+
sessionFile,
|
|
134
|
+
entryCount: lifecycleEntries.length,
|
|
135
|
+
sessionEntryCount,
|
|
136
|
+
lines
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
export {
|
|
140
|
+
resolveRunSessionFile,
|
|
141
|
+
buildRunReplay
|
|
142
|
+
};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
type ServerPhaseListener = (label: string) => void;
|
|
2
|
+
/** Returns the previously registered listener so scopes can restore it. */
|
|
3
|
+
export declare function setServerPhaseListener(listener: ServerPhaseListener | null): ServerPhaseListener | null;
|
|
4
|
+
export declare function setGitHubBearerTokenForCurrentProcess(token: string | null, projectRoot?: string): void;
|
|
5
|
+
export declare function ensureServerForCli(projectRoot: string): Promise<{
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
authToken: string | null;
|
|
8
|
+
connectionKind: "local" | "remote";
|
|
9
|
+
serverProjectRoot: string | null;
|
|
10
|
+
}>;
|
|
11
|
+
export interface WorkspaceTaskFilters {
|
|
12
|
+
readonly assignee?: string;
|
|
13
|
+
readonly state?: string;
|
|
14
|
+
readonly status?: string;
|
|
15
|
+
readonly limit?: number;
|
|
16
|
+
}
|
|
17
|
+
export type WorkspaceTaskRecord = Record<string, unknown> & {
|
|
18
|
+
readonly id?: unknown;
|
|
19
|
+
readonly title?: unknown;
|
|
20
|
+
readonly status?: unknown;
|
|
21
|
+
};
|
|
22
|
+
export type SubmitTaskRunInput = {
|
|
23
|
+
runId: string;
|
|
24
|
+
taskId?: string;
|
|
25
|
+
title?: string;
|
|
26
|
+
runtimeAdapter: "claude-code" | "codex" | "pi";
|
|
27
|
+
model?: string;
|
|
28
|
+
runtimeMode: string;
|
|
29
|
+
interactionMode: string;
|
|
30
|
+
initialPrompt?: string;
|
|
31
|
+
baselineMode?: "head" | "dirty-snapshot";
|
|
32
|
+
prMode?: "auto" | "ask" | "off";
|
|
33
|
+
};
|
|
34
|
+
export declare function requestServerJson(context: {
|
|
35
|
+
projectRoot: string;
|
|
36
|
+
}, pathname: string, init?: RequestInit): Promise<unknown>;
|
|
37
|
+
export declare function listWorkspaceTasksViaServer(context: {
|
|
38
|
+
projectRoot: string;
|
|
39
|
+
}, filters?: WorkspaceTaskFilters): Promise<WorkspaceTaskRecord[]>;
|
|
40
|
+
export declare function getWorkspaceTaskViaServer(context: {
|
|
41
|
+
projectRoot: string;
|
|
42
|
+
}, taskId: string): Promise<WorkspaceTaskRecord | null>;
|
|
43
|
+
export declare function selectNextWorkspaceTaskViaServer(context: {
|
|
44
|
+
projectRoot: string;
|
|
45
|
+
}, filters?: WorkspaceTaskFilters): Promise<{
|
|
46
|
+
task: WorkspaceTaskRecord | null;
|
|
47
|
+
count: number;
|
|
48
|
+
}>;
|
|
49
|
+
/**
|
|
50
|
+
* Submit a run (task or ad-hoc) to the local rig server. Routes to
|
|
51
|
+
* /api/runs/task vs /api/runs/adhoc based on whether a taskId is provided.
|
|
52
|
+
*
|
|
53
|
+
* Caller is responsible for any pre-flight (e.g. project sync). This helper
|
|
54
|
+
* only performs the POST and surfaces server errors as CliError.
|
|
55
|
+
*/
|
|
56
|
+
export declare function getGitHubAuthStatusViaServer(context: {
|
|
57
|
+
projectRoot: string;
|
|
58
|
+
}): Promise<Record<string, unknown>>;
|
|
59
|
+
export declare function postGitHubTokenViaServer(context: {
|
|
60
|
+
projectRoot: string;
|
|
61
|
+
}, token: string, options?: {
|
|
62
|
+
readonly selectedRepo?: string;
|
|
63
|
+
readonly projectRoot?: string;
|
|
64
|
+
}): Promise<Record<string, unknown>>;
|
|
65
|
+
export declare function prepareRemoteCheckoutViaServer(context: {
|
|
66
|
+
projectRoot: string;
|
|
67
|
+
}, input: {
|
|
68
|
+
repoSlug: string;
|
|
69
|
+
checkout: Record<string, unknown>;
|
|
70
|
+
repoUrl?: string;
|
|
71
|
+
baseDir?: string;
|
|
72
|
+
}): Promise<Record<string, unknown>>;
|
|
73
|
+
export declare function registerProjectViaServer(context: {
|
|
74
|
+
projectRoot: string;
|
|
75
|
+
}, input: {
|
|
76
|
+
repoSlug: string;
|
|
77
|
+
checkout?: Record<string, unknown>;
|
|
78
|
+
}): Promise<Record<string, unknown>>;
|
|
79
|
+
export declare function switchServerProjectRootViaServer(context: {
|
|
80
|
+
projectRoot: string;
|
|
81
|
+
}, projectRoot: string, options?: {
|
|
82
|
+
timeoutMs?: number;
|
|
83
|
+
pollMs?: number;
|
|
84
|
+
}): Promise<Record<string, unknown>>;
|
|
85
|
+
export declare function listRunsViaServer(context: {
|
|
86
|
+
projectRoot: string;
|
|
87
|
+
}, options?: {
|
|
88
|
+
limit?: number;
|
|
89
|
+
}): Promise<Record<string, unknown>[]>;
|
|
90
|
+
export declare function getRunDetailsViaServer(context: {
|
|
91
|
+
projectRoot: string;
|
|
92
|
+
}, runId: string): Promise<Record<string, unknown>>;
|
|
93
|
+
export declare function getRunLogsViaServer(context: {
|
|
94
|
+
projectRoot: string;
|
|
95
|
+
}, runId: string, options?: {
|
|
96
|
+
limit?: number;
|
|
97
|
+
cursor?: string;
|
|
98
|
+
}): Promise<Record<string, unknown>>;
|
|
99
|
+
export declare function getRunTimelineViaServer(context: {
|
|
100
|
+
projectRoot: string;
|
|
101
|
+
}, runId: string, options?: {
|
|
102
|
+
limit?: number;
|
|
103
|
+
cursor?: string;
|
|
104
|
+
}): Promise<Record<string, unknown>>;
|
|
105
|
+
export declare function ensureTaskLabelsViaServer(context: {
|
|
106
|
+
projectRoot: string;
|
|
107
|
+
}): Promise<Record<string, unknown>>;
|
|
108
|
+
export declare function listGitHubProjectsViaServer(context: {
|
|
109
|
+
projectRoot: string;
|
|
110
|
+
}, owner: string): Promise<Record<string, unknown>>;
|
|
111
|
+
export declare function getGitHubProjectStatusFieldViaServer(context: {
|
|
112
|
+
projectRoot: string;
|
|
113
|
+
}, projectId: string): Promise<Record<string, unknown>>;
|
|
114
|
+
export declare function updateWorkspaceTaskViaServer(context: {
|
|
115
|
+
projectRoot: string;
|
|
116
|
+
}, input: {
|
|
117
|
+
id: string;
|
|
118
|
+
status?: string;
|
|
119
|
+
comment?: string;
|
|
120
|
+
title?: string;
|
|
121
|
+
body?: string;
|
|
122
|
+
issueNodeId?: string | null;
|
|
123
|
+
}): Promise<Record<string, unknown>>;
|
|
124
|
+
/**
|
|
125
|
+
* Resume (or restart) a run through the selected server — works against the
|
|
126
|
+
* auto-started local daemon AND a remote connection, unlike the old
|
|
127
|
+
* runtime-side path that could only spawn a local engine-checkout server.
|
|
128
|
+
* Without an explicit run id, targets the most recently updated resumable
|
|
129
|
+
* run known to the server.
|
|
130
|
+
*/
|
|
131
|
+
export declare function resumeRunViaServer(context: {
|
|
132
|
+
projectRoot: string;
|
|
133
|
+
}, runId: string | null, options: {
|
|
134
|
+
restart: boolean;
|
|
135
|
+
}): Promise<Record<string, unknown>>;
|
|
136
|
+
/** Short human label for the selected server — board/header decoration. */
|
|
137
|
+
export declare function resolveServerConnectionLabel(projectRoot: string): Promise<string>;
|
|
138
|
+
export declare function stopRunViaServer(context: {
|
|
139
|
+
projectRoot: string;
|
|
140
|
+
}, runId: string): Promise<Record<string, unknown>>;
|
|
141
|
+
export declare function steerRunViaServer(context: {
|
|
142
|
+
projectRoot: string;
|
|
143
|
+
}, runId: string, message: string): Promise<Record<string, unknown>>;
|
|
144
|
+
export declare function getRunPiSessionViaServer(context: {
|
|
145
|
+
projectRoot: string;
|
|
146
|
+
}, runId: string): Promise<Record<string, unknown>>;
|
|
147
|
+
export declare function getRunPiMessagesViaServer(context: {
|
|
148
|
+
projectRoot: string;
|
|
149
|
+
}, runId: string): Promise<Record<string, unknown>>;
|
|
150
|
+
export declare function getRunPiStatusViaServer(context: {
|
|
151
|
+
projectRoot: string;
|
|
152
|
+
}, runId: string): Promise<Record<string, unknown>>;
|
|
153
|
+
export declare function getRunPiCommandsViaServer(context: {
|
|
154
|
+
projectRoot: string;
|
|
155
|
+
}, runId: string): Promise<Record<string, unknown>>;
|
|
156
|
+
export declare function getRunPiCapabilitiesViaServer(context: {
|
|
157
|
+
projectRoot: string;
|
|
158
|
+
}, runId: string): Promise<Record<string, unknown>>;
|
|
159
|
+
export declare function sendRunPiPromptViaServer(context: {
|
|
160
|
+
projectRoot: string;
|
|
161
|
+
}, runId: string, text: string, streamingBehavior?: "steer" | "followUp"): Promise<Record<string, unknown>>;
|
|
162
|
+
export declare function sendRunPiShellViaServer(context: {
|
|
163
|
+
projectRoot: string;
|
|
164
|
+
}, runId: string, text: string): Promise<Record<string, unknown>>;
|
|
165
|
+
export declare function runRunPiCommandViaServer(context: {
|
|
166
|
+
projectRoot: string;
|
|
167
|
+
}, runId: string, text: string): Promise<Record<string, unknown>>;
|
|
168
|
+
export declare function respondRunPiExtensionUiViaServer(context: {
|
|
169
|
+
projectRoot: string;
|
|
170
|
+
}, runId: string, requestId: string, valueOrCancel: {
|
|
171
|
+
value?: unknown;
|
|
172
|
+
confirmed?: boolean;
|
|
173
|
+
cancelled?: boolean;
|
|
174
|
+
}): Promise<Record<string, unknown>>;
|
|
175
|
+
export declare function abortRunPiViaServer(context: {
|
|
176
|
+
projectRoot: string;
|
|
177
|
+
}, runId: string): Promise<Record<string, unknown>>;
|
|
178
|
+
export declare function buildRunPiEventsWebSocketUrl(context: {
|
|
179
|
+
projectRoot: string;
|
|
180
|
+
}, runId: string): Promise<string>;
|
|
181
|
+
export declare function submitTaskRunViaServer(context: {
|
|
182
|
+
projectRoot: string;
|
|
183
|
+
}, input: SubmitTaskRunInput): Promise<{
|
|
184
|
+
runId: string;
|
|
185
|
+
}>;
|
|
186
|
+
export {};
|