@crouton-kit/humanloop 0.3.38 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.d.ts +3 -2
- package/dist/api.js +2 -2
- package/dist/browser/server.d.ts +15 -5
- package/dist/browser/server.js +110 -14
- package/dist/cli.js +0 -0
- package/dist/editor/roundtrip.d.ts +5 -0
- package/dist/editor/roundtrip.js +36 -0
- package/dist/inbox/completion.js +1 -27
- package/dist/inbox/controller.d.ts +32 -3
- package/dist/inbox/controller.js +427 -35
- package/dist/inbox/convention.d.ts +9 -2
- package/dist/inbox/convention.js +51 -3
- package/dist/inbox/deck-adapter.d.ts +10 -2
- package/dist/inbox/deck-adapter.js +23 -12
- package/dist/inbox/deck-schema.d.ts +2 -0
- package/dist/inbox/deck-schema.js +4 -4
- package/dist/inbox/followup.d.ts +57 -0
- package/dist/inbox/followup.js +117 -0
- package/dist/inbox/registry.d.ts +4 -0
- package/dist/inbox/registry.js +9 -4
- package/dist/inbox/tickets.d.ts +5 -0
- package/dist/inbox/tickets.js +25 -32
- package/dist/inbox/tui.d.ts +1 -1
- package/dist/inbox/tui.js +58 -25
- package/dist/inbox/visual.d.ts +130 -0
- package/dist/inbox/visual.js +747 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +2 -1
- package/dist/tui/app.d.ts +3 -6
- package/dist/tui/app.js +130 -97
- package/dist/tui/input.d.ts +5 -1
- package/dist/tui/input.js +41 -15
- package/dist/tui/log.d.ts +2 -0
- package/dist/tui/log.js +53 -0
- package/dist/tui/render.js +44 -27
- package/dist/tui/terminal.d.ts +1 -0
- package/dist/tui/terminal.js +5 -0
- package/dist/tui/tmux.js +44 -22
- package/dist/types.d.ts +71 -7
- package/dist/web/assets/{index-DhbBiRqS.js → index-YFwgZZMg.js} +2 -2
- package/dist/web/index.html +1 -1
- package/package.json +6 -3
- package/dist/conversation/reader.d.ts +0 -6
- package/dist/conversation/reader.js +0 -58
- package/dist/visuals/generate.d.ts +0 -9
- package/dist/visuals/generate.js +0 -79
package/dist/inbox/tui.js
CHANGED
|
@@ -19,33 +19,66 @@ export function formatTimeAgo(iso) {
|
|
|
19
19
|
return 'just now';
|
|
20
20
|
}
|
|
21
21
|
/** Pure inbox rows; selection and terminal ownership belong to InboxController. */
|
|
22
|
-
export function buildInboxLines(items, width, selectedIndex) {
|
|
22
|
+
export function buildInboxLines(items, width, selectedIndex, height = Number.MAX_SAFE_INTEGER) {
|
|
23
23
|
if (items.length === 0)
|
|
24
24
|
return [` ${DIM}${ITALIC}No pending interactions${RESET}`];
|
|
25
|
-
const lines = [` ${BOLD}${items.length} pending${RESET}`, ''];
|
|
26
25
|
const contentWidth = width - 4;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const age = formatTimeAgo(item.blockedSince);
|
|
37
|
-
const source = truncateRow(rawSource, Math.max(8, contentWidth - age.length - 8 - 10));
|
|
38
|
-
const cursor = index === selectedIndex ? `${CYAN}▸${RESET} ` : ' ';
|
|
39
|
-
const titleWidth = Math.max(10, contentWidth - source.length - age.length - 8);
|
|
40
|
-
let row = `${cursor}${ansiColor(icon, KIND_COLOR[kind] ?? 'cyan')} `;
|
|
41
|
-
if (source)
|
|
42
|
-
row += `${ansiColor(source, 'yellow')} ${DIM}·${RESET} `;
|
|
43
|
-
row += `${BOLD}${truncateRow(item.title || `(${item.id.slice(0, 8)})`, titleWidth)}${RESET} ${DIM}${age}${RESET}`;
|
|
44
|
-
lines.push(row);
|
|
45
|
-
if (item.claim)
|
|
46
|
-
lines.push(` ${DIM}${truncateRow(`claimed by ${item.claim.owner}`, contentWidth - 6)}${RESET}`);
|
|
47
|
-
else if (item.subtitle)
|
|
48
|
-
lines.push(` ${DIM}${truncateRow(item.subtitle, contentWidth - 6)}${RESET}`);
|
|
49
|
-
}
|
|
26
|
+
const itemLines = items.map((item, index) => buildItemLines(item, index, selectedIndex, contentWidth));
|
|
27
|
+
const window = visibleWindow(itemLines, selectedIndex, Math.max(1, height - 2));
|
|
28
|
+
const lines = [` ${BOLD}${items.length} pending${RESET}`, ''];
|
|
29
|
+
if (window.start > 0)
|
|
30
|
+
lines.push(` ${DIM}↑ ${window.start} above${RESET}`);
|
|
31
|
+
for (let index = window.start; index < window.end; index++)
|
|
32
|
+
lines.push(...itemLines[index]);
|
|
33
|
+
if (window.end < items.length)
|
|
34
|
+
lines.push(` ${DIM}↓ ${items.length - window.end} below${RESET}`);
|
|
50
35
|
return lines;
|
|
51
36
|
}
|
|
37
|
+
function buildItemLines(item, index, selectedIndex, contentWidth) {
|
|
38
|
+
const kind = item.kind === 'deck' ? item.interactionKind ?? 'decision' : 'review';
|
|
39
|
+
const icon = KIND_ICON[kind] ?? '·';
|
|
40
|
+
// Source and title share the row budget: an unbounded source (a long node
|
|
41
|
+
// or session name) would floor the title at its minimum and overflow the
|
|
42
|
+
// column, bending the panel divider. Shrink the source only when the row
|
|
43
|
+
// cannot hold it alongside the title's 10-col minimum.
|
|
44
|
+
const rawSource = item.source.sessionName ?? item.source.askedBy ?? item.source.nodeId ?? '';
|
|
45
|
+
const age = formatTimeAgo(item.blockedSince);
|
|
46
|
+
const source = truncateRow(rawSource, Math.max(8, contentWidth - age.length - 8 - 10));
|
|
47
|
+
const cursor = index === selectedIndex ? `${CYAN}▸${RESET} ` : ' ';
|
|
48
|
+
const titleWidth = Math.max(10, contentWidth - source.length - age.length - 8);
|
|
49
|
+
let row = `${cursor}${ansiColor(icon, KIND_COLOR[kind] ?? 'cyan')} `;
|
|
50
|
+
if (source)
|
|
51
|
+
row += `${ansiColor(source, 'yellow')} ${DIM}·${RESET} `;
|
|
52
|
+
row += `${BOLD}${truncateRow(item.title || `(${item.id.slice(0, 8)})`, titleWidth)}${RESET} ${DIM}${age}${RESET}`;
|
|
53
|
+
if (item.claim)
|
|
54
|
+
return [row, ` ${DIM}${truncateRow(`claimed by ${item.claim.owner}`, contentWidth - 6)}${RESET}`];
|
|
55
|
+
if (item.subtitle)
|
|
56
|
+
return [row, ` ${DIM}${truncateRow(item.subtitle, contentWidth - 6)}${RESET}`];
|
|
57
|
+
return [row];
|
|
58
|
+
}
|
|
59
|
+
/** Select a contiguous row window that always contains the selected ticket. */
|
|
60
|
+
function visibleWindow(rows, selectedIndex, capacity) {
|
|
61
|
+
let start = Math.max(0, Math.min(selectedIndex, rows.length - 1));
|
|
62
|
+
let end = start + 1;
|
|
63
|
+
let preferBelow = true;
|
|
64
|
+
while (true) {
|
|
65
|
+
const below = end < rows.length ? { start, end: end + 1 } : undefined;
|
|
66
|
+
const above = start > 0 ? { start: start - 1, end } : undefined;
|
|
67
|
+
const preferred = preferBelow ? [below, above] : [above, below];
|
|
68
|
+
const next = preferred.find((candidate) => candidate !== undefined && windowHeight(rows, candidate.start, candidate.end) <= capacity);
|
|
69
|
+
if (next === undefined)
|
|
70
|
+
break;
|
|
71
|
+
start = next.start;
|
|
72
|
+
end = next.end;
|
|
73
|
+
preferBelow = !preferBelow;
|
|
74
|
+
}
|
|
75
|
+
return { start, end };
|
|
76
|
+
}
|
|
77
|
+
function windowHeight(rows, start, end) {
|
|
78
|
+
let height = start > 0 ? 1 : 0;
|
|
79
|
+
for (let index = start; index < end; index++)
|
|
80
|
+
height += rows[index].length;
|
|
81
|
+
if (end < rows.length)
|
|
82
|
+
height++;
|
|
83
|
+
return height;
|
|
84
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type { CanonicalInteraction, Interaction, VisualRequest as PanelVisualRequest } from '../types.js';
|
|
2
|
+
import { type CompletionHandler } from './registry.js';
|
|
3
|
+
export declare const VISUAL_CAPABILITY: "humanloop.visual/v1";
|
|
4
|
+
export interface VisualClaimIdentity {
|
|
5
|
+
token: string;
|
|
6
|
+
host: string;
|
|
7
|
+
pid: number;
|
|
8
|
+
claimedAt: string;
|
|
9
|
+
}
|
|
10
|
+
export interface VisualCleanupObligation {
|
|
11
|
+
reason: 'canceled' | 'unreceipted_start_error';
|
|
12
|
+
attempts: number;
|
|
13
|
+
nextAttemptAt: string;
|
|
14
|
+
lastAttemptAt?: string;
|
|
15
|
+
lastError?: string;
|
|
16
|
+
}
|
|
17
|
+
interface VisualBinding {
|
|
18
|
+
capability: typeof VISUAL_CAPABILITY;
|
|
19
|
+
owner: string;
|
|
20
|
+
root: string;
|
|
21
|
+
dir: string;
|
|
22
|
+
ticketId: string;
|
|
23
|
+
requestId: string;
|
|
24
|
+
generationId: string;
|
|
25
|
+
interactionId: string;
|
|
26
|
+
interaction: CanonicalInteraction;
|
|
27
|
+
claim: VisualClaimIdentity;
|
|
28
|
+
handler: CompletionHandler;
|
|
29
|
+
}
|
|
30
|
+
export interface VisualProtocolRequest extends VisualBinding {
|
|
31
|
+
schema: 'humanloop.visual-request/v1';
|
|
32
|
+
state: 'running' | 'canceled' | 'terminal';
|
|
33
|
+
requestedAt: string;
|
|
34
|
+
settledAt?: string;
|
|
35
|
+
cleanup?: VisualCleanupObligation;
|
|
36
|
+
}
|
|
37
|
+
export interface VisualRequestEvent extends VisualBinding {
|
|
38
|
+
schema: 'humanloop.visual-request-event/v1';
|
|
39
|
+
action: 'start' | 'cancel';
|
|
40
|
+
}
|
|
41
|
+
interface VisualResultBinding extends VisualBinding {
|
|
42
|
+
schema: 'humanloop.visual-result/v1';
|
|
43
|
+
completedAt: string;
|
|
44
|
+
}
|
|
45
|
+
export type VisualProtocolResult = (VisualResultBinding & {
|
|
46
|
+
status: 'ready';
|
|
47
|
+
markdown: string;
|
|
48
|
+
}) | (VisualResultBinding & {
|
|
49
|
+
status: 'error';
|
|
50
|
+
error: string;
|
|
51
|
+
});
|
|
52
|
+
export type VisualResultSubmission = {
|
|
53
|
+
requestId: string;
|
|
54
|
+
generationId: string;
|
|
55
|
+
interactionId: string;
|
|
56
|
+
interaction: CanonicalInteraction;
|
|
57
|
+
claimToken: string;
|
|
58
|
+
status: 'ready';
|
|
59
|
+
markdown: string;
|
|
60
|
+
} | {
|
|
61
|
+
requestId: string;
|
|
62
|
+
generationId: string;
|
|
63
|
+
interactionId: string;
|
|
64
|
+
interaction: CanonicalInteraction;
|
|
65
|
+
claimToken: string;
|
|
66
|
+
status: 'error';
|
|
67
|
+
error: string;
|
|
68
|
+
};
|
|
69
|
+
export interface StartVisualRequestOptions {
|
|
70
|
+
root: string;
|
|
71
|
+
dir: string;
|
|
72
|
+
claimToken: string;
|
|
73
|
+
request: PanelVisualRequest;
|
|
74
|
+
}
|
|
75
|
+
export type VisualStartDeliveryResult = 'delivered' | 'already_attempted' | 'ineligible' | 'failed';
|
|
76
|
+
export type VisualCleanupDeliveryResult = 'delivered' | 'pending' | 'none';
|
|
77
|
+
export interface StartedVisualRequest {
|
|
78
|
+
request: VisualProtocolRequest;
|
|
79
|
+
/** Resolves after the one permitted start attempt reaches a determinate outcome. */
|
|
80
|
+
delivery: Promise<VisualStartDeliveryResult>;
|
|
81
|
+
}
|
|
82
|
+
export interface VisualCleanupTask {
|
|
83
|
+
root: string;
|
|
84
|
+
dir: string;
|
|
85
|
+
requestId: string;
|
|
86
|
+
reason: VisualCleanupObligation['reason'];
|
|
87
|
+
nextAttemptAt: string;
|
|
88
|
+
}
|
|
89
|
+
/** Normalize one Interaction into the sole persisted/event correlation shape. */
|
|
90
|
+
export declare function canonicalizeInteraction(raw: Interaction | CanonicalInteraction): CanonicalInteraction;
|
|
91
|
+
/** Stable bytes used for every interaction equality check across the protocol. */
|
|
92
|
+
export declare function canonicalInteractionJson(raw: Interaction | CanonicalInteraction): string;
|
|
93
|
+
export declare function parseVisualRequestEvent(raw: unknown): VisualRequestEvent;
|
|
94
|
+
/** Strict, repairing reader; malformed or unbound request bytes return null. */
|
|
95
|
+
export declare function readVisualRequest(root: string, dir: string, requestId: string): VisualProtocolRequest | null;
|
|
96
|
+
/** Strict, repairing reader; canceled and mismatched results are never returned. */
|
|
97
|
+
export declare function readVisualResult(root: string, dir: string, requestId: string): VisualProtocolResult | null;
|
|
98
|
+
/** Decode an event and atomically bind it to Humanloop's immutable request state. */
|
|
99
|
+
export declare function readVisualRequestForEvent(raw: unknown): VisualProtocolRequest | null;
|
|
100
|
+
/** Persist one claim-bound request and dispatch its frozen handler at most once. */
|
|
101
|
+
export declare function startVisualRequest(opts: StartVisualRequestOptions): StartedVisualRequest;
|
|
102
|
+
/** Compare-publish the first fully correlated ready/error result. Stale writers are no-ops. */
|
|
103
|
+
export declare function submitVisualResult(root: string, dir: string, raw: VisualResultSubmission): {
|
|
104
|
+
published: boolean;
|
|
105
|
+
};
|
|
106
|
+
/** Attempt one due cleanup delivery through the request's frozen handler. */
|
|
107
|
+
export declare function dispatchVisualCleanup(root: string, dir: string, requestId: string): Promise<VisualCleanupDeliveryResult>;
|
|
108
|
+
/** State-first cancellation for one handle; the returned promise is cleanup delivery only. */
|
|
109
|
+
export declare function cancelVisualRequest(root: string, dir: string, requestId: string): Promise<VisualCleanupDeliveryResult>;
|
|
110
|
+
/** State-first cancel every running request, then dispatch every owed cleanup (including start failures). */
|
|
111
|
+
export declare function cancelVisualRequestsForTicket(root: string, dir: string): Promise<{
|
|
112
|
+
canceled: number;
|
|
113
|
+
cleanupOwed: number;
|
|
114
|
+
}>;
|
|
115
|
+
/** Durable tasks the next controller-owned retry executor should schedule. */
|
|
116
|
+
export declare function listVisualCleanupObligations(root: string, dir: string): VisualCleanupTask[];
|
|
117
|
+
export interface VisualRequestReconciliation {
|
|
118
|
+
retired: number;
|
|
119
|
+
cleanupOwed: number;
|
|
120
|
+
/** Cleanup delivery only; reconciliation never redelivers a start. */
|
|
121
|
+
delivery: Promise<VisualCleanupDeliveryResult[]>;
|
|
122
|
+
}
|
|
123
|
+
/** Retire abandoned generations under the ticket claim boundary. A live claim is
|
|
124
|
+
* authoritative; a newly acquired claim retires every older generation first. */
|
|
125
|
+
export declare function reconcileVisualRequestsForTicket(root: string, dir: string, currentClaimToken?: string): VisualRequestReconciliation;
|
|
126
|
+
/** Enumerate direct ticket children only, including resolved tickets whose cleanup is still owed. */
|
|
127
|
+
export declare function listVisualCleanupObligationsForRoot(root: string): VisualCleanupTask[];
|
|
128
|
+
/** Startup reconciliation only retires stale/missing-claim work; live owners stay untouched. */
|
|
129
|
+
export declare function reconcileStaleVisualRequestsForRoot(root: string): VisualRequestReconciliation[];
|
|
130
|
+
export {};
|