@bubblebrain-ai/bubble 0.0.25 → 0.0.27
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 +4 -2
- package/dist/agent.js +1 -1
- package/dist/clipboard.d.ts +14 -0
- package/dist/clipboard.js +132 -0
- package/dist/model-catalog.d.ts +3 -1
- package/dist/model-catalog.js +17 -28
- package/dist/prompt/compose.js +1 -1
- package/dist/provider-anthropic.d.ts +4 -0
- package/dist/provider-anthropic.js +31 -0
- package/dist/provider-ark-responses.d.ts +17 -0
- package/dist/provider-ark-responses.js +462 -0
- package/dist/provider-transform.js +7 -0
- package/dist/provider.d.ts +7 -0
- package/dist/provider.js +150 -22
- package/dist/slash-commands/commands.js +22 -0
- package/dist/tools/todo.js +22 -38
- package/dist/tui-ink/app.js +82 -62
- package/dist/tui-ink/input-box.d.ts +1 -0
- package/dist/tui-ink/input-box.js +23 -17
- package/dist/tui-ink/message-list.d.ts +17 -1
- package/dist/tui-ink/message-list.js +74 -13
- package/dist/tui-ink/model-picker.d.ts +3 -2
- package/dist/tui-ink/model-picker.js +17 -4
- package/dist/tui-ink/question-dialog.js +36 -10
- package/dist/tui-ink/run.js +14 -22
- package/dist/tui-ink/terminal-mouse.d.ts +11 -0
- package/dist/tui-ink/terminal-mouse.js +13 -0
- package/dist/tui-ink/welcome.js +13 -3
- package/dist/variant/variant-resolver.js +4 -1
- package/package.json +1 -1
- package/dist/tui/transcript-scroll.d.ts +0 -25
- package/dist/tui/transcript-scroll.js +0 -20
- package/dist/tui-ink/transcript-input.d.ts +0 -8
- package/dist/tui-ink/transcript-input.js +0 -9
- package/dist/tui-ink/transcript-viewport-math.d.ts +0 -10
- package/dist/tui-ink/transcript-viewport-math.js +0 -16
- package/dist/tui-ink/transcript-viewport.d.ts +0 -24
- package/dist/tui-ink/transcript-viewport.js +0 -83
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Transcript scroll-follow policy.
|
|
3
|
-
*
|
|
4
|
-
* The transcript snaps to the bottom ("follows") while the user is at the
|
|
5
|
-
* bottom, and stays put while they read older history. Two events override a
|
|
6
|
-
* scrolled-up position and re-engage following:
|
|
7
|
-
* - the user sends a message (explicit intent to watch the newest turn)
|
|
8
|
-
* - an approval prompt appears (requires the user's attention)
|
|
9
|
-
*
|
|
10
|
-
* Those renders set `forcePending`, which must survive until the deferred
|
|
11
|
-
* scroll actually runs: streaming redraws in the interim recompute the follow
|
|
12
|
-
* flag from the (still unscrolled) position and would otherwise cancel the
|
|
13
|
-
* snap. A user mouse scroll clears the pending force — their latest gesture
|
|
14
|
-
* always wins.
|
|
15
|
-
*/
|
|
16
|
-
export function resolveTranscriptScroll(state) {
|
|
17
|
-
if (state.forcePending)
|
|
18
|
-
return "scroll-bottom";
|
|
19
|
-
return state.shouldFollow && state.following ? "scroll-bottom" : "sync-position";
|
|
20
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export type TranscriptPageScrollDirection = "up" | "down";
|
|
2
|
-
export interface TranscriptKeyEvent {
|
|
3
|
-
pageUp?: boolean;
|
|
4
|
-
pageDown?: boolean;
|
|
5
|
-
}
|
|
6
|
-
export declare function transcriptPageScrollDirection(key: TranscriptKeyEvent, options: {
|
|
7
|
-
overlayActive: boolean;
|
|
8
|
-
}): TranscriptPageScrollDirection | undefined;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure scroll arithmetic for the alt-screen transcript viewport.
|
|
3
|
-
*
|
|
4
|
-
* Mirrors the historical transcript viewport semantics: "at bottom" tolerates a
|
|
5
|
-
* one-line slack so sub-line rounding never flips the follow flag while the
|
|
6
|
-
* user sits at the end of the transcript.
|
|
7
|
-
*/
|
|
8
|
-
export declare function maxScrollTop(contentHeight: number, viewportHeight: number): number;
|
|
9
|
-
export declare function clampScrollTop(scrollTop: number, contentHeight: number, viewportHeight: number): number;
|
|
10
|
-
export declare function isAtBottom(scrollTop: number, contentHeight: number, viewportHeight: number): boolean;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure scroll arithmetic for the alt-screen transcript viewport.
|
|
3
|
-
*
|
|
4
|
-
* Mirrors the historical transcript viewport semantics: "at bottom" tolerates a
|
|
5
|
-
* one-line slack so sub-line rounding never flips the follow flag while the
|
|
6
|
-
* user sits at the end of the transcript.
|
|
7
|
-
*/
|
|
8
|
-
export function maxScrollTop(contentHeight, viewportHeight) {
|
|
9
|
-
return Math.max(0, contentHeight - viewportHeight);
|
|
10
|
-
}
|
|
11
|
-
export function clampScrollTop(scrollTop, contentHeight, viewportHeight) {
|
|
12
|
-
return Math.max(0, Math.min(scrollTop, maxScrollTop(contentHeight, viewportHeight)));
|
|
13
|
-
}
|
|
14
|
-
export function isAtBottom(scrollTop, contentHeight, viewportHeight) {
|
|
15
|
-
return scrollTop >= maxScrollTop(contentHeight, viewportHeight) - 1;
|
|
16
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
export interface TranscriptViewportHandle {
|
|
3
|
-
/**
|
|
4
|
-
* Re-engage bottom-follow. Sets the pending force flag from
|
|
5
|
-
* transcript-scroll.ts, so the snap survives streaming renders that land
|
|
6
|
-
* between the request and the next measured layout.
|
|
7
|
-
*/
|
|
8
|
-
forceScrollToBottom(): void;
|
|
9
|
-
/** Scroll by N lines (negative = up). A user gesture: cancels a pending force. */
|
|
10
|
-
scrollBy(lines: number): void;
|
|
11
|
-
scrollPage(direction: "up" | "down"): void;
|
|
12
|
-
}
|
|
13
|
-
interface TranscriptViewportProps {
|
|
14
|
-
children: React.ReactNode;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Height-clamped scrolling viewport for the alt-screen transcript. The outer
|
|
18
|
-
* box clips; the inner box carries the full transcript and slides via a
|
|
19
|
-
* negative top margin. Follow policy is the shared transcript-scroll.ts:
|
|
20
|
-
* stay snapped while at the bottom, hold position while reading history,
|
|
21
|
-
* snap back on send/approval via forceScrollToBottom().
|
|
22
|
-
*/
|
|
23
|
-
export declare const TranscriptViewport: React.ForwardRefExoticComponent<TranscriptViewportProps & React.RefAttributes<TranscriptViewportHandle>>;
|
|
24
|
-
export {};
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "react";
|
|
3
|
-
import { Box, measureElement } from "ink";
|
|
4
|
-
import { resolveTranscriptScroll } from "../tui/transcript-scroll.js";
|
|
5
|
-
import { clampScrollTop, isAtBottom, maxScrollTop } from "./transcript-viewport-math.js";
|
|
6
|
-
/**
|
|
7
|
-
* Height-clamped scrolling viewport for the alt-screen transcript. The outer
|
|
8
|
-
* box clips; the inner box carries the full transcript and slides via a
|
|
9
|
-
* negative top margin. Follow policy is the shared transcript-scroll.ts:
|
|
10
|
-
* stay snapped while at the bottom, hold position while reading history,
|
|
11
|
-
* snap back on send/approval via forceScrollToBottom().
|
|
12
|
-
*/
|
|
13
|
-
export const TranscriptViewport = forwardRef(function TranscriptViewport({ children }, ref) {
|
|
14
|
-
const viewportRef = useRef(null);
|
|
15
|
-
const contentRef = useRef(null);
|
|
16
|
-
const [scrollTop, setScrollTop] = useState(0);
|
|
17
|
-
const scrollTopRef = useRef(0);
|
|
18
|
-
const followingRef = useRef(true);
|
|
19
|
-
const forcePendingRef = useRef(false);
|
|
20
|
-
// forceScrollToBottom must work even when no other state changes in the
|
|
21
|
-
// same tick; bumping this guarantees a commit so the measuring effect runs.
|
|
22
|
-
const [, setScrollEpoch] = useState(0);
|
|
23
|
-
const applyScrollTop = (next) => {
|
|
24
|
-
scrollTopRef.current = next;
|
|
25
|
-
setScrollTop(next);
|
|
26
|
-
};
|
|
27
|
-
// measureElement returns the Yoga-computed size, valid only after layout —
|
|
28
|
-
// callable from effects and input handlers, never during render.
|
|
29
|
-
const measureHeights = () => ({
|
|
30
|
-
viewportHeight: viewportRef.current ? measureElement(viewportRef.current).height : 0,
|
|
31
|
-
contentHeight: contentRef.current ? measureElement(contentRef.current).height : 0,
|
|
32
|
-
});
|
|
33
|
-
// Content and viewport heights change with streaming text, tool expansion,
|
|
34
|
-
// resize, and bottom-stack visibility — no dependency list covers them
|
|
35
|
-
// all, so re-resolve after every commit. setState below bails out via
|
|
36
|
-
// Object.is when nothing moved, so the steady state does not loop.
|
|
37
|
-
useEffect(() => {
|
|
38
|
-
const { viewportHeight, contentHeight } = measureHeights();
|
|
39
|
-
if (viewportHeight <= 0)
|
|
40
|
-
return;
|
|
41
|
-
const action = resolveTranscriptScroll({
|
|
42
|
-
forcePending: forcePendingRef.current,
|
|
43
|
-
shouldFollow: followingRef.current,
|
|
44
|
-
following: followingRef.current,
|
|
45
|
-
});
|
|
46
|
-
if (action === "scroll-bottom") {
|
|
47
|
-
forcePendingRef.current = false;
|
|
48
|
-
followingRef.current = true;
|
|
49
|
-
applyScrollTop(maxScrollTop(contentHeight, viewportHeight));
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
const clamped = clampScrollTop(scrollTopRef.current, contentHeight, viewportHeight);
|
|
53
|
-
followingRef.current = isAtBottom(clamped, contentHeight, viewportHeight);
|
|
54
|
-
if (clamped !== scrollTopRef.current)
|
|
55
|
-
applyScrollTop(clamped);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
useImperativeHandle(ref, () => {
|
|
59
|
-
const scrollBy = (lines) => {
|
|
60
|
-
forcePendingRef.current = false; // the user's latest gesture wins
|
|
61
|
-
const { viewportHeight, contentHeight } = measureHeights();
|
|
62
|
-
if (viewportHeight <= 0)
|
|
63
|
-
return;
|
|
64
|
-
const next = clampScrollTop(scrollTopRef.current + lines, contentHeight, viewportHeight);
|
|
65
|
-
followingRef.current = isAtBottom(next, contentHeight, viewportHeight);
|
|
66
|
-
if (next !== scrollTopRef.current)
|
|
67
|
-
applyScrollTop(next);
|
|
68
|
-
};
|
|
69
|
-
return {
|
|
70
|
-
forceScrollToBottom() {
|
|
71
|
-
forcePendingRef.current = true;
|
|
72
|
-
setScrollEpoch((epoch) => epoch + 1);
|
|
73
|
-
},
|
|
74
|
-
scrollBy,
|
|
75
|
-
scrollPage(direction) {
|
|
76
|
-
const { viewportHeight } = measureHeights();
|
|
77
|
-
const step = Math.max(1, viewportHeight - 2);
|
|
78
|
-
scrollBy(direction === "up" ? -step : step);
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
}, []);
|
|
82
|
-
return (_jsx(Box, { ref: viewportRef, flexDirection: "column", flexGrow: 1, minHeight: 0, overflowY: "hidden", children: _jsx(Box, { ref: contentRef, flexDirection: "column", flexShrink: 0, marginTop: -scrollTop, children: children }) }));
|
|
83
|
-
});
|