@h-rig/contracts 0.0.6-alpha.103 → 0.0.6-alpha.119
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/dist/index.cjs +556 -50
- package/dist/index.mjs +556 -50
- package/dist/src/help-catalog.js +63 -50
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +556 -50
- package/dist/src/run-record.d.ts +45 -0
- package/dist/src/run-record.js +1 -0
- package/dist/src/run-session-journal.d.ts +36 -0
- package/dist/src/run-session-journal.js +89 -0
- package/dist/src/run-timeline.d.ts +9 -0
- package/dist/src/run-timeline.js +1360 -0
- package/dist/src/workflow-journal.d.ts +124 -0
- package/dist/src/workflow-journal.js +389 -0
- package/package.json +1 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { RunJournalProjection } from "./run-journal";
|
|
2
|
+
import type { RigRunTimelineEntry } from "./run-timeline";
|
|
3
|
+
export type UnifiedInboxRequest = {
|
|
4
|
+
readonly requestId: string;
|
|
5
|
+
readonly kind: "approval" | "input";
|
|
6
|
+
readonly title: string;
|
|
7
|
+
readonly body?: string | null;
|
|
8
|
+
readonly options?: readonly string[];
|
|
9
|
+
readonly requestedAt: string | null;
|
|
10
|
+
readonly source: "run";
|
|
11
|
+
};
|
|
12
|
+
/** Unified operator-facing run record shared by CLI, cockpit, relay, and client projection logic. */
|
|
13
|
+
export interface RunRecord {
|
|
14
|
+
readonly runId: string;
|
|
15
|
+
readonly taskId: string | null;
|
|
16
|
+
readonly title: string;
|
|
17
|
+
/** RunStatus from the folded journal, or a liveness-derived fallback. */
|
|
18
|
+
readonly status: string;
|
|
19
|
+
readonly source: "local" | "remote";
|
|
20
|
+
/** True when the run is currently discoverable (registry heartbeat or local host). */
|
|
21
|
+
readonly live: boolean;
|
|
22
|
+
readonly stale: boolean;
|
|
23
|
+
readonly startedAt: string | null;
|
|
24
|
+
readonly updatedAt: string | null;
|
|
25
|
+
readonly completedAt: string | null;
|
|
26
|
+
readonly joinLink: string | null;
|
|
27
|
+
readonly webLink: string | null;
|
|
28
|
+
readonly relayUrl: string | null;
|
|
29
|
+
readonly sessionPath: string | null;
|
|
30
|
+
readonly prUrl: string | null;
|
|
31
|
+
readonly worktreePath: string | null;
|
|
32
|
+
readonly pendingApprovals: number;
|
|
33
|
+
readonly pendingInputs: number;
|
|
34
|
+
readonly steeringCount: number;
|
|
35
|
+
readonly stallCount: number;
|
|
36
|
+
readonly errorSummary?: string | null;
|
|
37
|
+
/** Timeline entries folded from the same OMP session custom entries as the journal. */
|
|
38
|
+
readonly timeline: RigRunTimelineEntry[];
|
|
39
|
+
/** Pending rig.run.* approvals/inputs only; rig.workflow.inbox.* is intentionally dead. */
|
|
40
|
+
readonly inbox: UnifiedInboxRequest[];
|
|
41
|
+
/** Live collab cwd when present in registry/discovery. */
|
|
42
|
+
readonly collabCwd: string | null;
|
|
43
|
+
/** The full folded journal (empty projection when no journal was readable). */
|
|
44
|
+
readonly projection: RunJournalProjection;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// @bun
|
|
@@ -19,6 +19,42 @@ export declare function buildStopSentinel(runId: string, reason?: string | null,
|
|
|
19
19
|
export declare function parseStopSentinel(text: string, expectedRunId: string): {
|
|
20
20
|
reason: string | null;
|
|
21
21
|
} | null;
|
|
22
|
+
export declare const RIG_PAUSE_SENTINEL = "<<RIG_PAUSE";
|
|
23
|
+
export declare const RIG_RESUME_SENTINEL = "<<RIG_RESUME";
|
|
24
|
+
export declare const RIG_CONTROL_SENTINEL_END = ">>";
|
|
25
|
+
export declare function buildPauseSentinel(runId: string, requestedBy?: string): string;
|
|
26
|
+
export declare function parsePauseSentinel(text: string, expectedRunId: string): {
|
|
27
|
+
requestedBy: string | null;
|
|
28
|
+
} | null;
|
|
29
|
+
export declare function buildResumeSentinel(runId: string, requestedBy?: string): string;
|
|
30
|
+
export declare function parseResumeSentinel(text: string, expectedRunId: string): {
|
|
31
|
+
requestedBy: string | null;
|
|
32
|
+
} | null;
|
|
33
|
+
export type RunInboxResolutionSentinel = {
|
|
34
|
+
kind: "approval";
|
|
35
|
+
requestId: string;
|
|
36
|
+
decision: "approve" | "reject";
|
|
37
|
+
note?: string | null;
|
|
38
|
+
requestedBy: string | null;
|
|
39
|
+
} | {
|
|
40
|
+
kind: "input";
|
|
41
|
+
requestId: string;
|
|
42
|
+
answers: Record<string, string>;
|
|
43
|
+
requestedBy: string | null;
|
|
44
|
+
};
|
|
45
|
+
export declare const RIG_INBOX_RESOLUTION_SENTINEL = "<<RIG_INBOX_RESOLUTION";
|
|
46
|
+
export type RunInboxResolutionInit = {
|
|
47
|
+
kind: "approval";
|
|
48
|
+
requestId: string;
|
|
49
|
+
decision: "approve" | "reject";
|
|
50
|
+
note?: string | null;
|
|
51
|
+
} | {
|
|
52
|
+
kind: "input";
|
|
53
|
+
requestId: string;
|
|
54
|
+
answers: Record<string, string>;
|
|
55
|
+
};
|
|
56
|
+
export declare function buildInboxResolutionSentinel(runId: string, resolution: RunInboxResolutionInit, requestedBy?: string): string;
|
|
57
|
+
export declare function parseInboxResolutionSentinel(text: string, expectedRunId: string): RunInboxResolutionSentinel | null;
|
|
22
58
|
/**
|
|
23
59
|
* The OMP session id embedded in a session journal filename
|
|
24
60
|
* (`<ISO-timestamp>_<sessionId>.jsonl`). This is a run's CANONICAL id — the same
|
|
@@ -1499,6 +1499,85 @@ function parseStopSentinel(text, expectedRunId) {
|
|
|
1499
1499
|
const reason = body.match(/(?:^|\s)reason=(.+)$/)?.[1]?.trim() ?? null;
|
|
1500
1500
|
return { reason };
|
|
1501
1501
|
}
|
|
1502
|
+
var RIG_PAUSE_SENTINEL = "<<RIG_PAUSE";
|
|
1503
|
+
var RIG_RESUME_SENTINEL = "<<RIG_RESUME";
|
|
1504
|
+
var RIG_CONTROL_SENTINEL_END = ">>";
|
|
1505
|
+
function buildControlSentinel(marker, runId, requestedBy) {
|
|
1506
|
+
return `${marker} runId=${runId} requestedBy=${requestedBy}${RIG_CONTROL_SENTINEL_END}`;
|
|
1507
|
+
}
|
|
1508
|
+
function parseControlSentinel(marker, text, expectedRunId) {
|
|
1509
|
+
const start = text.indexOf(marker);
|
|
1510
|
+
if (start < 0)
|
|
1511
|
+
return null;
|
|
1512
|
+
const end = text.indexOf(RIG_CONTROL_SENTINEL_END, start);
|
|
1513
|
+
const body = text.slice(start + marker.length, end >= 0 ? end : undefined).trim();
|
|
1514
|
+
const runId = body.match(/(?:^|\s)runId=([^\s>]+)/)?.[1] ?? "";
|
|
1515
|
+
if (runId && runId !== expectedRunId)
|
|
1516
|
+
return null;
|
|
1517
|
+
const requestedBy = body.match(/(?:^|\s)requestedBy=([^\s>]+)/)?.[1] ?? null;
|
|
1518
|
+
return { requestedBy };
|
|
1519
|
+
}
|
|
1520
|
+
function buildPauseSentinel(runId, requestedBy = "rig") {
|
|
1521
|
+
return buildControlSentinel(RIG_PAUSE_SENTINEL, runId, requestedBy);
|
|
1522
|
+
}
|
|
1523
|
+
function parsePauseSentinel(text, expectedRunId) {
|
|
1524
|
+
return parseControlSentinel(RIG_PAUSE_SENTINEL, text, expectedRunId);
|
|
1525
|
+
}
|
|
1526
|
+
function buildResumeSentinel(runId, requestedBy = "rig") {
|
|
1527
|
+
return buildControlSentinel(RIG_RESUME_SENTINEL, runId, requestedBy);
|
|
1528
|
+
}
|
|
1529
|
+
function parseResumeSentinel(text, expectedRunId) {
|
|
1530
|
+
return parseControlSentinel(RIG_RESUME_SENTINEL, text, expectedRunId);
|
|
1531
|
+
}
|
|
1532
|
+
var RIG_INBOX_RESOLUTION_SENTINEL = "<<RIG_INBOX_RESOLUTION";
|
|
1533
|
+
function encodeInboxResolutionPayload(payload) {
|
|
1534
|
+
return encodeURIComponent(JSON.stringify(payload));
|
|
1535
|
+
}
|
|
1536
|
+
function decodeInboxResolutionPayload(payload) {
|
|
1537
|
+
try {
|
|
1538
|
+
const parsed = JSON.parse(decodeURIComponent(payload));
|
|
1539
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
1540
|
+
return null;
|
|
1541
|
+
const record = parsed;
|
|
1542
|
+
if (record.kind === "approval") {
|
|
1543
|
+
const requestId = typeof record.requestId === "string" ? record.requestId.trim() : "";
|
|
1544
|
+
const decision = record.decision === "approve" || record.decision === "reject" ? record.decision : null;
|
|
1545
|
+
const note = typeof record.note === "string" ? record.note : record.note === null ? null : undefined;
|
|
1546
|
+
if (!requestId || !decision)
|
|
1547
|
+
return null;
|
|
1548
|
+
return { kind: "approval", requestId, decision, ...note !== undefined ? { note } : {} };
|
|
1549
|
+
}
|
|
1550
|
+
if (record.kind === "input") {
|
|
1551
|
+
const requestId = typeof record.requestId === "string" ? record.requestId.trim() : "";
|
|
1552
|
+
const answers = record.answers && typeof record.answers === "object" && !Array.isArray(record.answers) ? Object.fromEntries(Object.entries(record.answers).filter((entry) => typeof entry[1] === "string")) : null;
|
|
1553
|
+
if (!requestId || !answers)
|
|
1554
|
+
return null;
|
|
1555
|
+
return { kind: "input", requestId, answers };
|
|
1556
|
+
}
|
|
1557
|
+
} catch {
|
|
1558
|
+
return null;
|
|
1559
|
+
}
|
|
1560
|
+
return null;
|
|
1561
|
+
}
|
|
1562
|
+
function buildInboxResolutionSentinel(runId, resolution, requestedBy = "rig") {
|
|
1563
|
+
return `${RIG_INBOX_RESOLUTION_SENTINEL} runId=${runId} requestedBy=${requestedBy} data=${encodeInboxResolutionPayload(resolution)}${RIG_CONTROL_SENTINEL_END}`;
|
|
1564
|
+
}
|
|
1565
|
+
function parseInboxResolutionSentinel(text, expectedRunId) {
|
|
1566
|
+
const start = text.indexOf(RIG_INBOX_RESOLUTION_SENTINEL);
|
|
1567
|
+
if (start < 0)
|
|
1568
|
+
return null;
|
|
1569
|
+
const end = text.indexOf(RIG_CONTROL_SENTINEL_END, start);
|
|
1570
|
+
const body = text.slice(start + RIG_INBOX_RESOLUTION_SENTINEL.length, end >= 0 ? end : undefined).trim();
|
|
1571
|
+
const runId = body.match(/(?:^|\s)runId=([^\s>]+)/)?.[1] ?? "";
|
|
1572
|
+
if (runId && runId !== expectedRunId)
|
|
1573
|
+
return null;
|
|
1574
|
+
const requestedBy = body.match(/(?:^|\s)requestedBy=([^\s>]+)/)?.[1] ?? null;
|
|
1575
|
+
const payload = body.match(/(?:^|\s)data=([^\s>]+)/)?.[1] ?? "";
|
|
1576
|
+
const decoded = decodeInboxResolutionPayload(payload);
|
|
1577
|
+
if (!decoded)
|
|
1578
|
+
return null;
|
|
1579
|
+
return { ...decoded, requestedBy };
|
|
1580
|
+
}
|
|
1502
1581
|
function sessionIdFromSessionFile(sessionPath) {
|
|
1503
1582
|
if (!sessionPath)
|
|
1504
1583
|
return null;
|
|
@@ -1560,9 +1639,15 @@ function foldRunSessionEntries(entries, runId) {
|
|
|
1560
1639
|
export {
|
|
1561
1640
|
sessionIdFromSessionFile,
|
|
1562
1641
|
parseStopSentinel,
|
|
1642
|
+
parseResumeSentinel,
|
|
1643
|
+
parsePauseSentinel,
|
|
1644
|
+
parseInboxResolutionSentinel,
|
|
1563
1645
|
isRunSessionCustomType,
|
|
1564
1646
|
foldRunSessionEntries,
|
|
1565
1647
|
buildStopSentinel,
|
|
1648
|
+
buildResumeSentinel,
|
|
1649
|
+
buildPauseSentinel,
|
|
1650
|
+
buildInboxResolutionSentinel,
|
|
1566
1651
|
TYPE_FOR_CUSTOM,
|
|
1567
1652
|
RIG_STOP_SENTINEL_END,
|
|
1568
1653
|
RIG_STOP_SENTINEL,
|
|
@@ -1578,5 +1663,9 @@ export {
|
|
|
1578
1663
|
RIG_RUN_APPROVAL_RESOLVED,
|
|
1579
1664
|
RIG_RUN_APPROVAL_REQUESTED,
|
|
1580
1665
|
RIG_RUN_ADOPTED,
|
|
1666
|
+
RIG_RESUME_SENTINEL,
|
|
1667
|
+
RIG_PAUSE_SENTINEL,
|
|
1668
|
+
RIG_INBOX_RESOLUTION_SENTINEL,
|
|
1669
|
+
RIG_CONTROL_SENTINEL_END,
|
|
1581
1670
|
CUSTOM_TYPE_FOR
|
|
1582
1671
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type RunSessionCustomEntry } from "./run-session-journal";
|
|
2
|
+
export type RigRunTimelineEntry = {
|
|
3
|
+
at: string | null;
|
|
4
|
+
type: string;
|
|
5
|
+
stage?: string | null;
|
|
6
|
+
status?: string | null;
|
|
7
|
+
detail?: string | null;
|
|
8
|
+
};
|
|
9
|
+
export declare function timelineEntriesFromCustomEntries(entries: readonly RunSessionCustomEntry[]): readonly RigRunTimelineEntry[];
|