@on-par/factory-tui 0.0.0-stage → 0.9.1

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.
Files changed (115) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +14 -2
  3. package/dist/components/App.d.ts +38 -0
  4. package/dist/components/App.d.ts.map +1 -0
  5. package/dist/components/App.js +383 -0
  6. package/dist/components/App.js.map +1 -0
  7. package/dist/components/ApprovalPrompt.d.ts +9 -0
  8. package/dist/components/ApprovalPrompt.d.ts.map +1 -0
  9. package/dist/components/ApprovalPrompt.js +11 -0
  10. package/dist/components/ApprovalPrompt.js.map +1 -0
  11. package/dist/components/Dashboard.d.ts +16 -0
  12. package/dist/components/Dashboard.d.ts.map +1 -0
  13. package/dist/components/Dashboard.js +20 -0
  14. package/dist/components/Dashboard.js.map +1 -0
  15. package/dist/components/EventFeed.d.ts +7 -0
  16. package/dist/components/EventFeed.d.ts.map +1 -0
  17. package/dist/components/EventFeed.js +21 -0
  18. package/dist/components/EventFeed.js.map +1 -0
  19. package/dist/components/Header.d.ts +8 -0
  20. package/dist/components/Header.d.ts.map +1 -0
  21. package/dist/components/Header.js +13 -0
  22. package/dist/components/Header.js.map +1 -0
  23. package/dist/components/LaneList.d.ts +21 -0
  24. package/dist/components/LaneList.d.ts.map +1 -0
  25. package/dist/components/LaneList.js +48 -0
  26. package/dist/components/LaneList.js.map +1 -0
  27. package/dist/components/LaneRow.d.ts +18 -0
  28. package/dist/components/LaneRow.d.ts.map +1 -0
  29. package/dist/components/LaneRow.js +36 -0
  30. package/dist/components/LaneRow.js.map +1 -0
  31. package/dist/components/LaneView.d.ts +26 -0
  32. package/dist/components/LaneView.d.ts.map +1 -0
  33. package/dist/components/LaneView.js +38 -0
  34. package/dist/components/LaneView.js.map +1 -0
  35. package/dist/components/PhaseRow.d.ts +11 -0
  36. package/dist/components/PhaseRow.d.ts.map +1 -0
  37. package/dist/components/PhaseRow.js +28 -0
  38. package/dist/components/PhaseRow.js.map +1 -0
  39. package/dist/components/RunDetail.d.ts +14 -0
  40. package/dist/components/RunDetail.d.ts.map +1 -0
  41. package/dist/components/RunDetail.js +11 -0
  42. package/dist/components/RunDetail.js.map +1 -0
  43. package/dist/components/SteeringComposer.d.ts +8 -0
  44. package/dist/components/SteeringComposer.d.ts.map +1 -0
  45. package/dist/components/SteeringComposer.js +6 -0
  46. package/dist/components/SteeringComposer.js.map +1 -0
  47. package/dist/components/StopBanner.d.ts +6 -0
  48. package/dist/components/StopBanner.d.ts.map +1 -0
  49. package/dist/components/StopBanner.js +6 -0
  50. package/dist/components/StopBanner.js.map +1 -0
  51. package/dist/dashboard.d.ts +66 -0
  52. package/dist/dashboard.d.ts.map +1 -0
  53. package/dist/dashboard.js +157 -0
  54. package/dist/dashboard.js.map +1 -0
  55. package/dist/fallback.d.ts +8 -0
  56. package/dist/fallback.d.ts.map +1 -0
  57. package/dist/fallback.js +13 -0
  58. package/dist/fallback.js.map +1 -0
  59. package/dist/index.d.ts +45 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +24 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/lane-queue.d.ts +20 -0
  64. package/dist/lane-queue.d.ts.map +1 -0
  65. package/dist/lane-queue.js +20 -0
  66. package/dist/lane-queue.js.map +1 -0
  67. package/dist/run-tui.d.ts +20 -0
  68. package/dist/run-tui.d.ts.map +1 -0
  69. package/dist/run-tui.js +30 -0
  70. package/dist/run-tui.js.map +1 -0
  71. package/dist/state.d.ts +18 -0
  72. package/dist/state.d.ts.map +1 -0
  73. package/dist/state.js +77 -0
  74. package/dist/state.js.map +1 -0
  75. package/dist/tabs/CostsTab.d.ts +13 -0
  76. package/dist/tabs/CostsTab.d.ts.map +1 -0
  77. package/dist/tabs/CostsTab.js +24 -0
  78. package/dist/tabs/CostsTab.js.map +1 -0
  79. package/dist/tabs/HealthTab.d.ts +20 -0
  80. package/dist/tabs/HealthTab.d.ts.map +1 -0
  81. package/dist/tabs/HealthTab.js +18 -0
  82. package/dist/tabs/HealthTab.js.map +1 -0
  83. package/dist/tabs/LogTab.d.ts +10 -0
  84. package/dist/tabs/LogTab.d.ts.map +1 -0
  85. package/dist/tabs/LogTab.js +9 -0
  86. package/dist/tabs/LogTab.js.map +1 -0
  87. package/dist/tabs/QueueTab.d.ts +11 -0
  88. package/dist/tabs/QueueTab.d.ts.map +1 -0
  89. package/dist/tabs/QueueTab.js +37 -0
  90. package/dist/tabs/QueueTab.js.map +1 -0
  91. package/dist/tabs/TabBar.d.ts +7 -0
  92. package/dist/tabs/TabBar.d.ts.map +1 -0
  93. package/dist/tabs/TabBar.js +7 -0
  94. package/dist/tabs/TabBar.js.map +1 -0
  95. package/dist/tabs/health-window.d.ts +15 -0
  96. package/dist/tabs/health-window.d.ts.map +1 -0
  97. package/dist/tabs/health-window.js +50 -0
  98. package/dist/tabs/health-window.js.map +1 -0
  99. package/dist/tabs/log-scroll.d.ts +17 -0
  100. package/dist/tabs/log-scroll.d.ts.map +1 -0
  101. package/dist/tabs/log-scroll.js +32 -0
  102. package/dist/tabs/log-scroll.js.map +1 -0
  103. package/dist/tabs/run-costs.d.ts +40 -0
  104. package/dist/tabs/run-costs.d.ts.map +1 -0
  105. package/dist/tabs/run-costs.js +106 -0
  106. package/dist/tabs/run-costs.js.map +1 -0
  107. package/dist/tabs/types.d.ts +4 -0
  108. package/dist/tabs/types.d.ts.map +1 -0
  109. package/dist/tabs/types.js +9 -0
  110. package/dist/tabs/types.js.map +1 -0
  111. package/dist/text.d.ts +5 -0
  112. package/dist/text.d.ts.map +1 -0
  113. package/dist/text.js +8 -0
  114. package/dist/text.js.map +1 -0
  115. package/package.json +50 -4
@@ -0,0 +1,157 @@
1
+ import { laneStatusOf } from '@on-par/factory-core';
2
+ import { initialState, reduceEvent } from './state.js';
3
+ export function legacyFailurePointerFor(lane) {
4
+ return lane.status === 'parked' && !lane.failureEvidence ? lane.failReason : undefined;
5
+ }
6
+ export function initialDashboard() {
7
+ return { lanes: [], runDone: false };
8
+ }
9
+ /** Groups issue rows by their queue lane, lanes and rows both in first-seen order (#1736). */
10
+ export function lanesOf(state) {
11
+ const groups = new Map();
12
+ for (const row of state.lanes) {
13
+ const g = groups.get(row.lane);
14
+ if (g)
15
+ g.push(row);
16
+ else
17
+ groups.set(row.lane, [row]);
18
+ }
19
+ return [...groups].map(([lane, issues]) => ({ lane, issues }));
20
+ }
21
+ export function isLaneEvent(e) {
22
+ return /^\d+$/.test(e.issue);
23
+ }
24
+ const DEFAULT_LANE = 'default';
25
+ function newLane(e) {
26
+ return {
27
+ issue: e.issue,
28
+ lane: e.lane ?? DEFAULT_LANE,
29
+ run: initialState(),
30
+ status: 'running',
31
+ startedAt: e.ts,
32
+ lastEventAt: e.ts,
33
+ };
34
+ }
35
+ /** Lane statuses that mean "this lane is still doing something"; only these can go stale. */
36
+ const NON_TERMINAL = new Set(['running', 'ready', 'waiting-merge']);
37
+ /** True for lanes whose staleness depends on a heartbeat — the only ones worth polling a snapshot for. */
38
+ export function isNonTerminalLane(lane) {
39
+ return NON_TERMINAL.has(lane.status);
40
+ }
41
+ export function reduceDashboard(state, e) {
42
+ if (!isLaneEvent(e)) {
43
+ if (e.type === 'usage-stop')
44
+ return { ...state, usageStop: e.msg };
45
+ // A finished run has no active lanes by definition: drop them, so replaying a log that
46
+ // holds many runs leaves only the run in progress on the Active tab (#1369).
47
+ if (e.type === 'run-done')
48
+ return { ...state, lanes: [], runDone: true };
49
+ return state;
50
+ }
51
+ // After a run ended, only a run's own opening events (`issue-title`, a phase start) may open
52
+ // the next run's lane set. Out-of-run commands log numeric-issue events too — `factory land`
53
+ // logs `land` / `merged` / `fail` — and those must not resurrect a phantom lane (#1369).
54
+ if (state.runDone && !(e.type === 'issue-title' || laneStatusOf(e.type) === 'running'))
55
+ return state;
56
+ const base = state.runDone ? { ...state, lanes: [], runDone: false, usageStop: undefined } : state;
57
+ const idx = base.lanes.findIndex((l) => l.issue === e.issue);
58
+ const prevLane = idx === -1 ? newLane(e) : base.lanes[idx];
59
+ const prevStatus = prevLane.status;
60
+ let lane = {
61
+ ...prevLane,
62
+ lane: e.lane ?? prevLane.lane,
63
+ run: reduceEvent(prevLane.run, e),
64
+ reworkRound: e.rework ? Math.max(prevLane.reworkRound ?? 0, e.rework.round) : prevLane.reworkRound,
65
+ lastEventAt: e.ts,
66
+ };
67
+ if (laneStatusOf(e.type) === 'running' && prevStatus !== 'running') {
68
+ lane = {
69
+ ...lane,
70
+ status: 'running',
71
+ finishedAt: undefined,
72
+ failedPhase: undefined,
73
+ failReason: undefined,
74
+ failureEvidence: undefined,
75
+ waitingSince: undefined,
76
+ };
77
+ }
78
+ else if (e.type === 'issue-title') {
79
+ lane = { ...lane, title: e.msg };
80
+ }
81
+ else if (e.type === 'worktree') {
82
+ const prefix = 'Worktree ready at ';
83
+ lane = { ...lane, worktree: e.msg.startsWith(prefix) ? e.msg.slice(prefix.length) : lane.worktree };
84
+ }
85
+ else if (e.type === 'ready') {
86
+ lane = { ...lane, status: 'ready', prNumber: e.msg.match(/PR #(\d+)/)?.[1] ?? lane.prNumber };
87
+ }
88
+ else if (e.type === 'await-merge') {
89
+ lane = { ...lane, status: 'waiting-merge', waitingSince: lane.waitingSince ?? e.ts };
90
+ }
91
+ else if (e.type === 'landed' || e.type === 'merged') {
92
+ lane = { ...lane, status: 'merged', finishedAt: e.ts };
93
+ }
94
+ else if (laneStatusOf(e.type) === 'failed' || laneStatusOf(e.type) === 'parked') {
95
+ const capturedEvidence = e.evidence && e.fingerprint
96
+ ? {
97
+ reason: e.evidence.reason,
98
+ fingerprint: e.fingerprint,
99
+ eventExcerpt: e.evidence.eventExcerpt,
100
+ logPath: e.evidence.logPath,
101
+ relatedIssue: e.evidence.relatedIssue,
102
+ }
103
+ : undefined;
104
+ lane = {
105
+ ...lane,
106
+ status: laneStatusOf(e.type),
107
+ failedPhase: lane.failedPhase ?? lane.run.activePhase,
108
+ failReason: lane.failReason ?? e.msg,
109
+ failureEvidence: lane.failureEvidence ?? capturedEvidence,
110
+ finishedAt: e.ts,
111
+ };
112
+ }
113
+ else if (e.type === 'stopped') {
114
+ lane = { ...lane, status: 'stopped', finishedAt: e.ts };
115
+ }
116
+ const lanes = idx === -1 ? [...base.lanes, lane] : base.lanes.map((l, i) => (i === idx ? lane : l));
117
+ return { ...base, lanes };
118
+ }
119
+ /** Hides lanes a dead or killed run left behind at `running` / `ready` / `waiting-merge` (#1369).
120
+ * A lane stays visible while either its last event or its per-issue phase-snapshot heartbeat
121
+ * (`RunPhaseSnapshot.lastActivityAt`, keyed by issue in `heartbeats`) is within the threshold —
122
+ * the same rule `factory status` applies to local claims (ADR-0086). Terminal lanes are never
123
+ * hidden; `run-done` clears them. */
124
+ export function partitionLanesByActivity(lanes, opts) {
125
+ const fresh = (iso) => {
126
+ if (!iso)
127
+ return false;
128
+ const age = opts.now - Date.parse(iso);
129
+ return Number.isFinite(age) && age <= opts.staleThresholdMs;
130
+ };
131
+ const active = [];
132
+ let staleCount = 0;
133
+ for (const lane of lanes) {
134
+ if (!NON_TERMINAL.has(lane.status) || fresh(lane.lastEventAt) || fresh(opts.heartbeats?.[lane.issue])) {
135
+ active.push(lane);
136
+ }
137
+ else {
138
+ staleCount += 1;
139
+ }
140
+ }
141
+ return { active, staleCount };
142
+ }
143
+ export function mergeTrainPosition(state, issue) {
144
+ const waiting = state.lanes
145
+ .filter((l) => l.status === 'waiting-merge')
146
+ .sort((a, b) => {
147
+ const diff = Date.parse(a.waitingSince ?? '') - Date.parse(b.waitingSince ?? '');
148
+ return diff !== 0 ? diff : Number(a.issue) - Number(b.issue);
149
+ });
150
+ const idx = waiting.findIndex((l) => l.issue === issue);
151
+ return idx === -1 ? undefined : idx + 1;
152
+ }
153
+ export function laneElapsedMs(lane, now) {
154
+ const end = lane.finishedAt ? Date.parse(lane.finishedAt) : now;
155
+ return Math.max(0, end - Date.parse(lane.startedAt));
156
+ }
157
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { followEvents } from '@on-par/factory-core';
2
+ /**
3
+ * Plain-line fallback printer — mirrors `logEvent`'s console output
4
+ * (`[factory] ${type} #${issue}: ${msg}`) so non-TTY / Ink-init-failure
5
+ * sessions still see the same live feed `factory logs --follow` would show.
6
+ */
7
+ export declare function followPlain(eventsFile: string, out?: NodeJS.WritableStream, follow?: typeof followEvents): () => void;
8
+ //# sourceMappingURL=fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../src/fallback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGvE;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,GAAG,GAAE,MAAM,CAAC,cAA+B,EAC3C,MAAM,GAAE,OAAO,YAA2B,GACzC,MAAM,IAAI,CAQZ"}
@@ -0,0 +1,13 @@
1
+ import { followEvents } from '@on-par/factory-core';
2
+ import { colorEnabled, formatEventLine } from '@on-par/factory-core/internal';
3
+ /**
4
+ * Plain-line fallback printer — mirrors `logEvent`'s console output
5
+ * (`[factory] ${type} #${issue}: ${msg}`) so non-TTY / Ink-init-failure
6
+ * sessions still see the same live feed `factory logs --follow` would show.
7
+ */
8
+ export function followPlain(eventsFile, out = process.stdout, follow = followEvents) {
9
+ return follow(eventsFile, (e) => {
10
+ out.write(formatEventLine(e.type, e.issue, e.msg, { color: colorEnabled(out) }) + '\n');
11
+ }, { fromStart: true });
12
+ }
13
+ //# sourceMappingURL=fallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.js","sourceRoot":"","sources":["../src/fallback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAE9E;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,UAAkB,EAClB,GAAG,GAA0B,OAAO,CAAC,MAAM,EAC3C,MAAM,GAAwB,YAAY;IAE1C,OAAO,MAAM,CACX,UAAU,EACV,CAAC,CAAe,EAAE,EAAE;QAClB,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,GAA0B,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;IACjH,CAAC,EACD,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,45 @@
1
+ export type { AppProps, QueueReader } from './components/App.js';
2
+ export { App } from './components/App.js';
3
+ export type { ApprovalPromptProps } from './components/ApprovalPrompt.js';
4
+ export { ApprovalPrompt } from './components/ApprovalPrompt.js';
5
+ export type { DashboardProps } from './components/Dashboard.js';
6
+ export { Dashboard, laneCountsLine, staleLanesLine } from './components/Dashboard.js';
7
+ export type { EventFeedProps } from './components/EventFeed.js';
8
+ export { EventFeed } from './components/EventFeed.js';
9
+ export type { HeaderProps } from './components/Header.js';
10
+ export { Header } from './components/Header.js';
11
+ export type { LaneListProps, LaneSummary } from './components/LaneList.js';
12
+ export { LaneList, summarizeLane } from './components/LaneList.js';
13
+ export type { LaneViewProps, LaneViewRows } from './components/LaneView.js';
14
+ export { collapseMerged, LaneView } from './components/LaneView.js';
15
+ export type { LaneRowProps } from './components/LaneRow.js';
16
+ export { LaneRow } from './components/LaneRow.js';
17
+ export type { PhaseRowProps } from './components/PhaseRow.js';
18
+ export { formatDuration, formatElapsed, PhaseRow, spinnerFrame } from './components/PhaseRow.js';
19
+ export type { RunDetailProps } from './components/RunDetail.js';
20
+ export { RunDetail } from './components/RunDetail.js';
21
+ export type { StopBannerProps } from './components/StopBanner.js';
22
+ export { StopBanner } from './components/StopBanner.js';
23
+ export type { DashboardState, LaneActivityPartition, LaneGroup, LaneState, LaneStatus } from './dashboard.js';
24
+ export { initialDashboard, isLaneEvent, isNonTerminalLane, laneElapsedMs, lanesOf, mergeTrainPosition, partitionLanesByActivity, reduceDashboard, } from './dashboard.js';
25
+ export { followPlain } from './fallback.js';
26
+ export type { RunTuiOptions } from './run-tui.js';
27
+ export { runTui } from './run-tui.js';
28
+ export type { PhaseName, PhaseStatus, RunState } from './state.js';
29
+ export { initialState, isFailoverEvent, PHASES, reduceEvent } from './state.js';
30
+ export type { CostsTabProps } from './tabs/CostsTab.js';
31
+ export { CostsTab } from './tabs/CostsTab.js';
32
+ export type { LogScrollAction, LogScrollState, VisibleSlice } from './tabs/log-scroll.js';
33
+ export { initialLogScroll, reduceLogScroll, visibleSlice } from './tabs/log-scroll.js';
34
+ export type { LogTabProps } from './tabs/LogTab.js';
35
+ export { LogTab } from './tabs/LogTab.js';
36
+ export type { QueueTabProps } from './tabs/QueueTab.js';
37
+ export { QueueTab } from './tabs/QueueTab.js';
38
+ export type { TabBarProps } from './tabs/TabBar.js';
39
+ export { TabBar } from './tabs/TabBar.js';
40
+ export type { TabName } from './tabs/types.js';
41
+ export { TAB_LABELS, TAB_ORDER } from './tabs/types.js';
42
+ export { sanitizeTerminalText } from './text.js';
43
+ export type { LaneCostTotal, RunCostsSummary, RunIssueCost } from './tabs/run-costs.js';
44
+ export { formatTokensShort, resolveCostsSelection, summarizeRunCosts, truncateSegments } from './tabs/run-costs.js';
45
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAC1C,YAAY,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACtF,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACnE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpE,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACjG,YAAY,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,YAAY,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,qBAAqB,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC9G,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,OAAO,EACP,kBAAkB,EAClB,wBAAwB,EACxB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAChF,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACvF,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,24 @@
1
+ export { App } from './components/App.js';
2
+ export { ApprovalPrompt } from './components/ApprovalPrompt.js';
3
+ export { Dashboard, laneCountsLine, staleLanesLine } from './components/Dashboard.js';
4
+ export { EventFeed } from './components/EventFeed.js';
5
+ export { Header } from './components/Header.js';
6
+ export { LaneList, summarizeLane } from './components/LaneList.js';
7
+ export { collapseMerged, LaneView } from './components/LaneView.js';
8
+ export { LaneRow } from './components/LaneRow.js';
9
+ export { formatDuration, formatElapsed, PhaseRow, spinnerFrame } from './components/PhaseRow.js';
10
+ export { RunDetail } from './components/RunDetail.js';
11
+ export { StopBanner } from './components/StopBanner.js';
12
+ export { initialDashboard, isLaneEvent, isNonTerminalLane, laneElapsedMs, lanesOf, mergeTrainPosition, partitionLanesByActivity, reduceDashboard, } from './dashboard.js';
13
+ export { followPlain } from './fallback.js';
14
+ export { runTui } from './run-tui.js';
15
+ export { initialState, isFailoverEvent, PHASES, reduceEvent } from './state.js';
16
+ export { CostsTab } from './tabs/CostsTab.js';
17
+ export { initialLogScroll, reduceLogScroll, visibleSlice } from './tabs/log-scroll.js';
18
+ export { LogTab } from './tabs/LogTab.js';
19
+ export { QueueTab } from './tabs/QueueTab.js';
20
+ export { TabBar } from './tabs/TabBar.js';
21
+ export { TAB_LABELS, TAB_ORDER } from './tabs/types.js';
22
+ export { sanitizeTerminalText } from './text.js';
23
+ export { formatTokensShort, resolveCostsSelection, summarizeRunCosts, truncateSegments } from './tabs/run-costs.js';
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEtF,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEhD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAEjG,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAExD,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,OAAO,EACP,kBAAkB,EAClB,wBAAwB,EACxB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEhF,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEvF,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { QueueSnapshot } from '@on-par/factory-core';
2
+ import type { LaneState } from './dashboard.js';
3
+ export type LaneQueueRow = {
4
+ kind: 'queued';
5
+ issue: string;
6
+ title?: string;
7
+ position: number;
8
+ } | {
9
+ kind: 'parked';
10
+ issue: string;
11
+ title?: string;
12
+ };
13
+ export interface LaneQueueView {
14
+ rows: LaneQueueRow[];
15
+ /** Set when the queue read failed; rows is then empty. */
16
+ unavailable?: string;
17
+ }
18
+ /** The lane view's queue join (#1744): one lane's queued/parked issues the event log has not seen yet. */
19
+ export declare function laneQueueRows(lane: string, snapshot: QueueSnapshot, laneIssues: readonly LaneState[]): LaneQueueView;
20
+ //# sourceMappingURL=lane-queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lane-queue.d.ts","sourceRoot":"","sources":["../src/lane-queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,0GAA0G;AAC1G,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,SAAS,EAAE,GAAG,aAAa,CAapH"}
@@ -0,0 +1,20 @@
1
+ /** The lane view's queue join (#1744): one lane's queued/parked issues the event log has not seen yet. */
2
+ export function laneQueueRows(lane, snapshot, laneIssues) {
3
+ if (snapshot.error !== undefined)
4
+ return { rows: [], unavailable: snapshot.error };
5
+ const known = new Set(laneIssues.map((l) => l.issue));
6
+ const rows = [];
7
+ let position = 0;
8
+ for (const entry of snapshot.entries) {
9
+ if (entry.lane !== lane || known.has(String(entry.issue)))
10
+ continue;
11
+ const issue = String(entry.issue);
12
+ const title = entry.title !== undefined ? { title: entry.title } : {};
13
+ if (entry.status === 'parked')
14
+ rows.push({ kind: 'parked', issue, ...title });
15
+ else if (entry.status !== 'in-progress')
16
+ rows.push({ kind: 'queued', issue, ...title, position: ++position });
17
+ }
18
+ return { rows };
19
+ }
20
+ //# sourceMappingURL=lane-queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lane-queue.js","sourceRoot":"","sources":["../src/lane-queue.ts"],"names":[],"mappings":"AAcA,0GAA0G;AAC1G,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,QAAuB,EAAE,UAAgC;IACnG,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;IACnF,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACtD,MAAM,IAAI,GAAmB,EAAE,CAAC;IAChC,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QACrC,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAAE,SAAS;QACpE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,IAAI,KAAK,CAAC,MAAM,KAAK,QAAQ;YAAE,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;aACzE,IAAI,KAAK,CAAC,MAAM,KAAK,aAAa;YAAE,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { render } from 'ink';
2
+ import { type QueueReader } from './components/App.js';
3
+ import { followPlain } from './fallback.js';
4
+ export interface RunTuiOptions {
5
+ eventsFile: string;
6
+ repo?: string;
7
+ stopFile?: string;
8
+ queueReader?: QueueReader;
9
+ costsFile?: string;
10
+ approvalsDir?: string;
11
+ steeringDir?: string;
12
+ breakerFile?: string;
13
+ effectiveConfigLines?: string[];
14
+ runsDir?: string;
15
+ stdout?: NodeJS.WriteStream;
16
+ render?: typeof render;
17
+ followPlainFn?: typeof followPlain;
18
+ }
19
+ export declare function runTui(opts: RunTuiOptions): Promise<void>;
20
+ //# sourceMappingURL=run-tui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-tui.d.ts","sourceRoot":"","sources":["../src/run-tui.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,EAAO,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,OAAO,WAAW,CAAC;CACpC;AAcD,wBAAsB,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C/D"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render } from 'ink';
3
+ import { App } from './components/App.js';
4
+ import { followPlain } from './fallback.js';
5
+ function runPlain(eventsFile, stdout, followPlainFn) {
6
+ return new Promise((resolve) => {
7
+ const stop = followPlainFn(eventsFile, stdout);
8
+ const finish = () => {
9
+ stop();
10
+ resolve();
11
+ };
12
+ process.once('SIGINT', finish);
13
+ process.stdin.once('end', finish);
14
+ });
15
+ }
16
+ export async function runTui(opts) {
17
+ const { eventsFile, repo, stopFile, queueReader, costsFile, approvalsDir, steeringDir, breakerFile, effectiveConfigLines, runsDir, stdout = process.stdout, render: renderFn = render, followPlainFn = followPlain, } = opts;
18
+ if (!stdout.isTTY) {
19
+ await runPlain(eventsFile, stdout, followPlainFn);
20
+ return;
21
+ }
22
+ try {
23
+ const app = renderFn(_jsx(App, { eventsFile: eventsFile, repo: repo, stopFile: stopFile, queueReader: queueReader, costsFile: costsFile, approvalsDir: approvalsDir, steeringDir: steeringDir, breakerFile: breakerFile, effectiveConfigLines: effectiveConfigLines, runsDir: runsDir }), { exitOnCtrlC: true });
24
+ await app.waitUntilExit();
25
+ }
26
+ catch {
27
+ await runPlain(eventsFile, stdout, followPlainFn);
28
+ }
29
+ }
30
+ //# sourceMappingURL=run-tui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-tui.js","sourceRoot":"","sources":["../src/run-tui.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,EAAE,GAAG,EAAoB,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAkB5C,SAAS,QAAQ,CAAC,UAAkB,EAAE,MAA0B,EAAE,aAAiC;IACjG,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,GAAG,EAAE;YAClB,IAAI,EAAE,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAmB;IAC9C,MAAM,EACJ,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,WAAW,EACX,SAAS,EACT,YAAY,EACZ,WAAW,EACX,WAAW,EACX,oBAAoB,EACpB,OAAO,EACP,MAAM,GAAG,OAAO,CAAC,MAAM,EACvB,MAAM,EAAE,QAAQ,GAAG,MAAM,EACzB,aAAa,GAAG,WAAW,GAC5B,GAAG,IAAI,CAAC;IAET,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClB,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAClB,KAAC,GAAG,IACF,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,EACxB,oBAAoB,EAAE,oBAAoB,EAC1C,OAAO,EAAE,OAAO,GAChB,EACF,EAAE,WAAW,EAAE,IAAI,EAAE,CACtB,CAAC;QACF,MAAM,GAAG,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;IACpD,CAAC;AACH,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { type FactoryEvent } from '@on-par/factory-core';
2
+ export declare const PHASES: readonly ['PLAN', 'BUILD', 'CHECK', 'SHIP'];
3
+ export type PhaseName = (typeof PHASES)[number];
4
+ export type PhaseStatus = 'pending' | 'active' | 'done';
5
+ export interface RunState {
6
+ issue?: string;
7
+ activePhase?: PhaseName;
8
+ phaseStatus: Record<PhaseName, PhaseStatus>;
9
+ phaseStartedAt?: string;
10
+ model?: string;
11
+ route?: string;
12
+ done: boolean;
13
+ feed: FactoryEvent[];
14
+ }
15
+ export declare function initialState(): RunState;
16
+ export declare function isFailoverEvent(e: FactoryEvent): boolean;
17
+ export declare function reduceEvent(state: RunState, e: FactoryEvent): RunState;
18
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAErE,eAAO,MAAM,MAAM,YAAI,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAU,CAAC;AAClE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AAChD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAExD,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,YAAY,EAAE,CAAC;CACtB;AAED,wBAAgB,YAAY,IAAI,QAAQ,CAMvC;AAiBD,wBAAgB,eAAe,CAAC,CAAC,EAAE,YAAY,GAAG,OAAO,CAIxD;AAoBD,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,YAAY,GAAG,QAAQ,CAsCtE"}
package/dist/state.js ADDED
@@ -0,0 +1,77 @@
1
+ import { severityOf } from '@on-par/factory-core';
2
+ export const PHASES = ['PLAN', 'BUILD', 'CHECK', 'SHIP'];
3
+ export function initialState() {
4
+ return {
5
+ phaseStatus: { PLAN: 'pending', BUILD: 'pending', CHECK: 'pending', SHIP: 'pending' },
6
+ done: false,
7
+ feed: [],
8
+ };
9
+ }
10
+ const PHASE_BY_EVENT_TYPE = {
11
+ plan: 'PLAN',
12
+ build: 'BUILD',
13
+ check: 'CHECK',
14
+ rework: 'CHECK',
15
+ ship: 'SHIP',
16
+ };
17
+ const MODEL_TRYING_RE = /Trying (\S+) for/;
18
+ const MODEL_COMPLETE_RE = /complete with model (\S+?),?\s/;
19
+ const MODEL_TRAILING_RE = /with model (\S+)$/;
20
+ const ROUTE_RE = /route: (\S+?)\)?$/;
21
+ const FAILOVER_MSG_RE = /failing over|failed \(|Rate limited|timed out/;
22
+ export function isFailoverEvent(e) {
23
+ if (e.type === 'router' && FAILOVER_MSG_RE.test(e.msg))
24
+ return true;
25
+ const severity = severityOf(e.type);
26
+ return severity === 'warn' || severity === 'error';
27
+ }
28
+ function extractModel(e) {
29
+ if (e.model)
30
+ return e.model;
31
+ if (e.type === 'router') {
32
+ return e.msg.match(MODEL_TRYING_RE)?.[1];
33
+ }
34
+ if (e.type === 'plan' || e.type === 'build') {
35
+ return e.msg.match(MODEL_COMPLETE_RE)?.[1] ?? e.msg.match(MODEL_TRAILING_RE)?.[1];
36
+ }
37
+ return undefined;
38
+ }
39
+ function extractRoute(e) {
40
+ if (e.type === 'plan' || e.type === 'build') {
41
+ return e.msg.match(ROUTE_RE)?.[1];
42
+ }
43
+ return undefined;
44
+ }
45
+ export function reduceEvent(state, e) {
46
+ const feed = [...state.feed, e].slice(-10);
47
+ if (e.type === 'ready') {
48
+ return {
49
+ ...state,
50
+ phaseStatus: { PLAN: 'done', BUILD: 'done', CHECK: 'done', SHIP: 'done' },
51
+ activePhase: undefined,
52
+ done: true,
53
+ feed,
54
+ };
55
+ }
56
+ const phase = PHASE_BY_EVENT_TYPE[e.type];
57
+ const model = extractModel(e) ?? state.model;
58
+ const route = extractRoute(e) ?? state.route;
59
+ if (!phase) {
60
+ return { ...state, model, route, feed, issue: e.issue ?? state.issue };
61
+ }
62
+ const phaseChanged = state.activePhase !== phase;
63
+ const activeIndex = PHASES.indexOf(phase);
64
+ const phaseStatus = Object.fromEntries(PHASES.map((p, i) => [p, i < activeIndex ? 'done' : i === activeIndex ? 'active' : 'pending']));
65
+ return {
66
+ ...state,
67
+ issue: e.issue,
68
+ activePhase: phase,
69
+ phaseStatus,
70
+ phaseStartedAt: phaseChanged ? e.ts : state.phaseStartedAt,
71
+ model,
72
+ route,
73
+ done: false,
74
+ feed,
75
+ };
76
+ }
77
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { type CostsRead } from '@on-par/factory-core';
2
+ import { type JSX } from 'react';
3
+ import type { LaneState } from '../dashboard.js';
4
+ export interface CostsTabProps {
5
+ costs: CostsRead;
6
+ /** Current-run lanes from DashboardState (state.lanes, not the stale-filtered set). */
7
+ lanes: LaneState[];
8
+ selectedIssue?: string;
9
+ expanded?: boolean;
10
+ width?: number;
11
+ }
12
+ export declare function CostsTab({ costs, lanes, selectedIssue, expanded, width }: CostsTabProps): JSX.Element;
13
+ //# sourceMappingURL=CostsTab.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CostsTab.d.ts","sourceRoot":"","sources":["../../src/tabs/CostsTab.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEvE,OAAO,EAAE,KAAK,GAAG,EAAW,MAAM,OAAO,CAAC;AAE1C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,SAAS,CAAC;IACjB,uFAAuF;IACvF,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAID,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,QAAgB,EAAE,KAAW,EAAE,EAAE,aAAa,GAAG,GAAG,CAAC,OAAO,CAiFnH"}
@@ -0,0 +1,24 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { formatCostTotal } from '@on-par/factory-core';
3
+ import { Box, Text } from 'ink';
4
+ import { useMemo } from 'react';
5
+ import { formatTokensShort, resolveCostsSelection, summarizeRunCosts, truncateSegments } from './run-costs.js';
6
+ const usd = (cost, unpriced) => formatCostTotal(cost, unpriced, 2);
7
+ export function CostsTab({ costs, lanes, selectedIssue, expanded = false, width = 100 }) {
8
+ const summary = useMemo(() => summarizeRunCosts(costs.entries, lanes), [costs.entries, lanes]);
9
+ const warning = costs.skipped > 0 && (_jsxs(Text, { color: "yellow", children: ["\u26A0 skipped ", costs.skipped, " malformed line(s) in costs.jsonl"] }));
10
+ if (costs.entries.length === 0) {
11
+ return (_jsxs(Box, { flexDirection: "column", children: [warning, _jsx(Text, { dimColor: true, children: "no cost data yet" })] }));
12
+ }
13
+ const allTime = (_jsxs(Text, { dimColor: true, children: ["All-time (costs.jsonl): ", usd(summary.allTime.cost, summary.allTime.unpricedCount)] }));
14
+ if (summary.runStartedAt === undefined || summary.issues.length === 0) {
15
+ return (_jsxs(Box, { flexDirection: "column", children: [warning, _jsx(Text, { dimColor: true, children: summary.runStartedAt === undefined ? 'no active run' : 'no cost rows this run yet' }), allTime] }));
16
+ }
17
+ const currentId = resolveCostsSelection(summary, lanes, selectedIssue);
18
+ const current = summary.issues.find((i) => i.issue === currentId) ?? summary.issues[0];
19
+ const { total } = summary;
20
+ return (_jsxs(Box, { flexDirection: "column", children: [warning, _jsxs(Text, { children: [_jsx(Text, { bold: true, children: "Spent this run:" }), " ", usd(total.cost, total.unpricedCount), " \u00B7 in", ' ', formatTokensShort(total.inputTokens), " \u00B7 out ", formatTokensShort(total.outputTokens)] }), _jsxs(Text, { children: ["Median / merged PR:", ' ', summary.medianMergedCost === null
21
+ ? '— (0 merged)'
22
+ : `${usd(summary.medianMergedCost, 0)} (n=${summary.mergedCount})`] }), _jsx(Text, { children: truncateSegments('By lane: ', summary.byLane.map((l) => `${l.lane} ${usd(l.cost, l.unpricedCount)}`), width) }), _jsx(Text, { children: truncateSegments('By issue: ', summary.issues.map((i) => `#${i.issue} ${usd(i.cost, i.unpricedCount)}`), width) }), _jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "\u276F " }), "#", current.issue, " (lane ", current.lane, ") ", usd(current.cost, current.unpricedCount), " \u00B7 in ", formatTokensShort(current.inputTokens), " \u00B7 out ", formatTokensShort(current.outputTokens), ' ', _jsxs(Text, { dimColor: true, children: ["\u2014 \u2191\u2193 select \u00B7 ", expanded ? 'esc close' : '⏎ per-model'] })] }), expanded && (_jsxs(_Fragment, { children: [_jsxs(Text, { bold: true, children: ["per-model \u2014 #", current.issue] }), current.perModel.map((m) => (_jsxs(Text, { children: [' ', m.model, " ", m.tasks, " task(s) in ", formatTokensShort(m.inputTokens), " out ", formatTokensShort(m.outputTokens), ' ', usd(m.cost, m.unpricedCount)] }, m.model)))] })), _jsx(Text, { children: " " }), allTime] }));
23
+ }
24
+ //# sourceMappingURL=CostsTab.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CostsTab.js","sourceRoot":"","sources":["../../src/tabs/CostsTab.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,eAAe,EAAkB,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAY,OAAO,EAAE,MAAM,OAAO,CAAC;AAG1C,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAW/G,MAAM,GAAG,GAAG,CAAC,IAAmB,EAAE,QAAgB,EAAU,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;AAElG,MAAM,UAAU,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,GAAG,KAAK,EAAE,KAAK,GAAG,GAAG,EAAiB;IACpG,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/F,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,GAAG,CAAC,IAAI,CACnC,MAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,gCAAY,KAAK,CAAC,OAAO,yCAAyC,CACvF,CAAC;IAEF,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACxB,OAAO,EACR,KAAC,IAAI,IAAC,QAAQ,uCAAwB,IAClC,CACP,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,CACd,MAAC,IAAI,IAAC,QAAQ,+CAA0B,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,IAAQ,CACzG,CAAC;IAEF,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtE,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACxB,OAAO,EACR,KAAC,IAAI,IAAC,QAAQ,kBAAE,OAAO,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,2BAA2B,GAAQ,EACzG,OAAO,IACJ,CACP,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;IACvE,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACvF,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAE1B,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACxB,OAAO,EACR,MAAC,IAAI,eACH,KAAC,IAAI,IAAC,IAAI,sCAAuB,OAAE,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAO,GAAG,EAChF,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,kBAAS,iBAAiB,CAAC,KAAK,CAAC,YAAY,CAAC,IAC9E,EACP,MAAC,IAAI,sCACiB,GAAG,EACtB,OAAO,CAAC,gBAAgB,KAAK,IAAI;wBAChC,CAAC,CAAC,cAAc;wBAChB,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,WAAW,GAAG,IAC/D,EACP,KAAC,IAAI,cACF,gBAAgB,CACf,WAAW,EACX,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,EACtE,KAAK,CACN,GACI,EACP,KAAC,IAAI,cACF,gBAAgB,CACf,YAAY,EACZ,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,EACxE,KAAK,CACN,GACI,EACP,MAAC,IAAI,eACH,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,wBAAU,OAAE,OAAO,CAAC,KAAK,aAAS,OAAO,CAAC,IAAI,QAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC,iBACxG,iBAAiB,CAAC,OAAO,CAAC,WAAW,CAAC,kBAAS,iBAAiB,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,GAAG,EAC/F,MAAC,IAAI,IAAC,QAAQ,yDAAgB,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,IAAQ,IACvE,EACN,QAAQ,IAAI,CACX,8BACE,MAAC,IAAI,IAAC,IAAI,yCAAe,OAAO,CAAC,KAAK,IAAQ,EAC7C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAC3B,MAAC,IAAI,eACF,IAAI,EACJ,CAAC,CAAC,KAAK,OAAG,CAAC,CAAC,KAAK,kBAAc,iBAAiB,CAAC,CAAC,CAAC,WAAW,CAAC,WAAO,iBAAiB,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,GAAG,EAC5G,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,KAHpB,CAAC,CAAC,KAAK,CAIX,CACR,CAAC,IACD,CACJ,EACD,KAAC,IAAI,oBAAS,EACb,OAAO,IACJ,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { type CostEntry, type FactoryEvent } from '@on-par/factory-core';
2
+ import { type JSX } from 'react';
3
+ import { type HealthWindowName } from './health-window.js';
4
+ export interface BreakerRow {
5
+ provider: string;
6
+ reason: string;
7
+ remainingMs: number;
8
+ }
9
+ export interface HealthTabProps {
10
+ events: FactoryEvent[];
11
+ costs: CostEntry[];
12
+ breakers: BreakerRow[];
13
+ effectiveConfigLines: string[];
14
+ showSecondary: boolean;
15
+ window: HealthWindowName;
16
+ runStartedAt?: string;
17
+ now: number;
18
+ }
19
+ export declare function HealthTab({ events, costs, breakers, effectiveConfigLines, showSecondary, window, runStartedAt, now, }: HealthTabProps): JSX.Element;
20
+ //# sourceMappingURL=HealthTab.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HealthTab.d.ts","sourceRoot":"","sources":["../../src/tabs/HealthTab.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,SAAS,EAAE,KAAK,YAAY,EAAkB,MAAM,sBAAsB,CAAC;AAE5G,OAAO,EAAE,KAAK,GAAG,EAAW,MAAM,OAAO,CAAC;AAE1C,OAAO,EAIL,KAAK,gBAAgB,EAEtB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,gBAAgB,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,SAAS,CAAC,EACxB,MAAM,EACN,KAAK,EACL,QAAQ,EACR,oBAAoB,EACpB,aAAa,EACb,MAAM,EACN,YAAY,EACZ,GAAG,GACJ,EAAE,cAAc,GAAG,GAAG,CAAC,OAAO,CAkD9B"}
@@ -0,0 +1,18 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { computeHealthKpis, formatKpiLines } from '@on-par/factory-core';
3
+ import { Box, Text } from 'ink';
4
+ import { useMemo } from 'react';
5
+ import { filterToWindow, formatHealthHeadline, HEALTH_WINDOW_LABELS, resolveHealthWindowStart, } from './health-window.js';
6
+ export function HealthTab({ events, costs, breakers, effectiveConfigLines, showSecondary, window, runStartedAt, now, }) {
7
+ const startMs = resolveHealthWindowStart(window, runStartedAt, now);
8
+ // Bucket 24h starts to the minute so the 500ms `now` tick doesn't recompute every frame.
9
+ const memoStart = startMs === null ? null : window === '24h' ? Math.floor(startMs / 60_000) * 60_000 : startMs;
10
+ const kpis = useMemo(() => {
11
+ const w = filterToWindow(events, costs, memoStart);
12
+ return computeHealthKpis(w.events, w.costs);
13
+ }, [events, costs, memoStart]);
14
+ const headline = formatHealthHeadline(kpis);
15
+ const kpiLines = formatKpiLines(kpis);
16
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsxs(Text, { bold: true, children: ["Health \u2014 ", HEALTH_WINDOW_LABELS[window]] }), _jsx(Text, { dimColor: true, children: " w window \u00B7 e details" })] }), breakers.length === 0 ? (_jsxs(Text, { children: ['Breaker:'.padEnd(22), "closed"] })) : (breakers.map((b) => (_jsxs(Text, { color: "yellow", children: ['Breaker:'.padEnd(22), b.provider, ": OPEN (", b.reason, ") \u2014 ", Math.ceil(b.remainingMs / 60_000), "m remaining"] }, b.provider)))), headline.map((row) => (_jsx(Text, { children: row.label.padEnd(22) + row.value }, row.label))), _jsx(Text, { children: " " }), showSecondary ? (_jsxs(_Fragment, { children: [_jsx(Text, { bold: true, children: "Effective config:" }), effectiveConfigLines.length === 0 ? (_jsx(Text, { dimColor: true, children: "(unavailable)" })) : (effectiveConfigLines.map((line, i) => _jsx(Text, { children: line }, i))), _jsx(Text, { children: " " }), _jsx(Text, { bold: true, children: "KPIs:" }), kpiLines.map((line, i) => (_jsx(Text, { children: line }, i)))] })) : (_jsx(Text, { dimColor: true, children: "(Effective config and full KPIs hidden \u2014 press e to view)" }))] }));
17
+ }
18
+ //# sourceMappingURL=HealthTab.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HealthTab.js","sourceRoot":"","sources":["../../src/tabs/HealthTab.tsx"],"names":[],"mappings":"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"}