@bubblebrain-ai/bubble 0.0.24 → 0.0.26

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 (171) hide show
  1. package/README.md +5 -3
  2. package/dist/agent.js +1 -1
  3. package/dist/clipboard.d.ts +14 -0
  4. package/dist/clipboard.js +132 -0
  5. package/dist/config.d.ts +3 -0
  6. package/dist/config.js +22 -6
  7. package/dist/goal/format.js +34 -4
  8. package/dist/goal/store.d.ts +3 -0
  9. package/dist/goal/store.js +14 -1
  10. package/dist/goal/usage.d.ts +2 -0
  11. package/dist/goal/usage.js +3 -0
  12. package/dist/main.js +23 -42
  13. package/dist/model-catalog.d.ts +3 -1
  14. package/dist/model-catalog.js +17 -28
  15. package/dist/prompt/compose.js +1 -1
  16. package/dist/provider-anthropic.d.ts +4 -0
  17. package/dist/provider-anthropic.js +31 -0
  18. package/dist/provider-ark-responses.d.ts +17 -0
  19. package/dist/provider-ark-responses.js +462 -0
  20. package/dist/provider-transform.js +7 -0
  21. package/dist/provider.d.ts +7 -0
  22. package/dist/provider.js +170 -27
  23. package/dist/slash-commands/commands.js +22 -0
  24. package/dist/tools/todo.js +22 -38
  25. package/dist/tui/detect-theme.d.ts +1 -0
  26. package/dist/tui/detect-theme.js +23 -0
  27. package/dist/tui/image-display.d.ts +13 -0
  28. package/dist/tui/image-display.js +49 -0
  29. package/dist/tui/input-history.d.ts +37 -6
  30. package/dist/tui/input-history.js +194 -23
  31. package/dist/tui/model-switch.d.ts +42 -0
  32. package/dist/tui/model-switch.js +55 -0
  33. package/dist/tui-ink/app.d.ts +32 -2
  34. package/dist/tui-ink/app.js +1409 -549
  35. package/dist/tui-ink/approval/select.js +10 -0
  36. package/dist/tui-ink/detect-theme.d.ts +1 -2
  37. package/dist/tui-ink/detect-theme.js +1 -87
  38. package/dist/tui-ink/display-history.d.ts +1 -0
  39. package/dist/tui-ink/display-history.js +11 -0
  40. package/dist/tui-ink/feedback-dialog.js +10 -0
  41. package/dist/tui-ink/feishu-setup-picker.js +10 -0
  42. package/dist/tui-ink/footer.d.ts +1 -0
  43. package/dist/tui-ink/footer.js +8 -2
  44. package/dist/tui-ink/input-box.d.ts +71 -9
  45. package/dist/tui-ink/input-box.js +359 -121
  46. package/dist/tui-ink/input-history.d.ts +1 -16
  47. package/dist/tui-ink/input-history.js +1 -79
  48. package/dist/tui-ink/input-queue.d.ts +12 -0
  49. package/dist/tui-ink/input-queue.js +17 -0
  50. package/dist/tui-ink/key-events.d.ts +9 -0
  51. package/dist/tui-ink/key-events.js +8 -0
  52. package/dist/tui-ink/markdown.js +1 -1
  53. package/dist/tui-ink/message-list.d.ts +19 -1
  54. package/dist/tui-ink/message-list.js +111 -32
  55. package/dist/tui-ink/model-picker.d.ts +25 -2
  56. package/dist/tui-ink/model-picker.js +237 -20
  57. package/dist/tui-ink/plan-confirm.js +10 -0
  58. package/dist/tui-ink/question-dialog.js +46 -10
  59. package/dist/tui-ink/run.d.ts +10 -1
  60. package/dist/tui-ink/run.js +27 -42
  61. package/dist/tui-ink/session-picker.js +3 -0
  62. package/dist/tui-ink/submit-dedupe.d.ts +5 -0
  63. package/dist/tui-ink/submit-dedupe.js +25 -0
  64. package/dist/tui-ink/terminal-mouse.d.ts +24 -1
  65. package/dist/tui-ink/terminal-mouse.js +76 -21
  66. package/dist/tui-ink/theme.d.ts +6 -3
  67. package/dist/tui-ink/theme.js +10 -4
  68. package/dist/tui-ink/welcome.d.ts +1 -0
  69. package/dist/tui-ink/welcome.js +34 -27
  70. package/dist/variant/variant-resolver.js +4 -1
  71. package/package.json +1 -5
  72. package/dist/tui/clipboard.d.ts +0 -1
  73. package/dist/tui/clipboard.js +0 -53
  74. package/dist/tui/escape-confirmation.d.ts +0 -15
  75. package/dist/tui/escape-confirmation.js +0 -30
  76. package/dist/tui/global-key-router.d.ts +0 -3
  77. package/dist/tui/global-key-router.js +0 -87
  78. package/dist/tui/markdown-inline.d.ts +0 -22
  79. package/dist/tui/markdown-inline.js +0 -68
  80. package/dist/tui/markdown-theme-rules.d.ts +0 -23
  81. package/dist/tui/markdown-theme-rules.js +0 -164
  82. package/dist/tui/markdown-theme.d.ts +0 -5
  83. package/dist/tui/markdown-theme.js +0 -27
  84. package/dist/tui/opencode-spinner.d.ts +0 -22
  85. package/dist/tui/opencode-spinner.js +0 -216
  86. package/dist/tui/prompt-keybindings.d.ts +0 -42
  87. package/dist/tui/prompt-keybindings.js +0 -35
  88. package/dist/tui/render-signature.d.ts +0 -1
  89. package/dist/tui/render-signature.js +0 -7
  90. package/dist/tui/run.d.ts +0 -67
  91. package/dist/tui/run.js +0 -10166
  92. package/dist/tui/sidebar-mcp.d.ts +0 -31
  93. package/dist/tui/sidebar-mcp.js +0 -62
  94. package/dist/tui/sidebar-state.d.ts +0 -12
  95. package/dist/tui/sidebar-state.js +0 -69
  96. package/dist/tui/streaming-tool-args.d.ts +0 -15
  97. package/dist/tui/streaming-tool-args.js +0 -30
  98. package/dist/tui/tool-renderers/fallback.d.ts +0 -2
  99. package/dist/tui/tool-renderers/fallback.js +0 -75
  100. package/dist/tui/tool-renderers/registry.d.ts +0 -3
  101. package/dist/tui/tool-renderers/registry.js +0 -11
  102. package/dist/tui/tool-renderers/subagent.d.ts +0 -2
  103. package/dist/tui/tool-renderers/subagent.js +0 -135
  104. package/dist/tui/tool-renderers/types.d.ts +0 -36
  105. package/dist/tui/tool-renderers/types.js +0 -1
  106. package/dist/tui/tool-renderers/write-preview.d.ts +0 -12
  107. package/dist/tui/tool-renderers/write-preview.js +0 -32
  108. package/dist/tui/tool-renderers/write.d.ts +0 -6
  109. package/dist/tui/tool-renderers/write.js +0 -88
  110. package/dist/tui/transcript-scroll.d.ts +0 -25
  111. package/dist/tui/transcript-scroll.js +0 -20
  112. package/dist/tui-ink/transcript-viewport-math.d.ts +0 -11
  113. package/dist/tui-ink/transcript-viewport-math.js +0 -17
  114. package/dist/tui-ink/transcript-viewport.d.ts +0 -24
  115. package/dist/tui-ink/transcript-viewport.js +0 -83
  116. package/dist/tui-opentui/app.d.ts +0 -54
  117. package/dist/tui-opentui/app.js +0 -1371
  118. package/dist/tui-opentui/approval/approval-dialog.d.ts +0 -15
  119. package/dist/tui-opentui/approval/approval-dialog.js +0 -155
  120. package/dist/tui-opentui/approval/diff-view.d.ts +0 -9
  121. package/dist/tui-opentui/approval/diff-view.js +0 -43
  122. package/dist/tui-opentui/approval/select.d.ts +0 -37
  123. package/dist/tui-opentui/approval/select.js +0 -91
  124. package/dist/tui-opentui/detect-theme.d.ts +0 -2
  125. package/dist/tui-opentui/detect-theme.js +0 -87
  126. package/dist/tui-opentui/display-history.d.ts +0 -56
  127. package/dist/tui-opentui/display-history.js +0 -130
  128. package/dist/tui-opentui/edit-diff.d.ts +0 -11
  129. package/dist/tui-opentui/edit-diff.js +0 -57
  130. package/dist/tui-opentui/feedback-dialog.d.ts +0 -21
  131. package/dist/tui-opentui/feedback-dialog.js +0 -164
  132. package/dist/tui-opentui/feishu-setup-picker.d.ts +0 -7
  133. package/dist/tui-opentui/feishu-setup-picker.js +0 -272
  134. package/dist/tui-opentui/file-mentions.d.ts +0 -29
  135. package/dist/tui-opentui/file-mentions.js +0 -174
  136. package/dist/tui-opentui/footer.d.ts +0 -26
  137. package/dist/tui-opentui/footer.js +0 -40
  138. package/dist/tui-opentui/image-paste.d.ts +0 -54
  139. package/dist/tui-opentui/image-paste.js +0 -288
  140. package/dist/tui-opentui/input-box.d.ts +0 -32
  141. package/dist/tui-opentui/input-box.js +0 -462
  142. package/dist/tui-opentui/input-history.d.ts +0 -16
  143. package/dist/tui-opentui/input-history.js +0 -79
  144. package/dist/tui-opentui/markdown.d.ts +0 -66
  145. package/dist/tui-opentui/markdown.js +0 -127
  146. package/dist/tui-opentui/message-list.d.ts +0 -31
  147. package/dist/tui-opentui/message-list.js +0 -131
  148. package/dist/tui-opentui/model-picker.d.ts +0 -63
  149. package/dist/tui-opentui/model-picker.js +0 -450
  150. package/dist/tui-opentui/plan-confirm.d.ts +0 -9
  151. package/dist/tui-opentui/plan-confirm.js +0 -124
  152. package/dist/tui-opentui/question-dialog.d.ts +0 -10
  153. package/dist/tui-opentui/question-dialog.js +0 -110
  154. package/dist/tui-opentui/recent-activity.d.ts +0 -8
  155. package/dist/tui-opentui/recent-activity.js +0 -71
  156. package/dist/tui-opentui/run-session-picker.d.ts +0 -10
  157. package/dist/tui-opentui/run-session-picker.js +0 -28
  158. package/dist/tui-opentui/run.d.ts +0 -38
  159. package/dist/tui-opentui/run.js +0 -48
  160. package/dist/tui-opentui/session-picker.d.ts +0 -12
  161. package/dist/tui-opentui/session-picker.js +0 -120
  162. package/dist/tui-opentui/theme.d.ts +0 -89
  163. package/dist/tui-opentui/theme.js +0 -157
  164. package/dist/tui-opentui/todos.d.ts +0 -9
  165. package/dist/tui-opentui/todos.js +0 -45
  166. package/dist/tui-opentui/trace-groups.d.ts +0 -27
  167. package/dist/tui-opentui/trace-groups.js +0 -455
  168. package/dist/tui-opentui/use-terminal-size.d.ts +0 -4
  169. package/dist/tui-opentui/use-terminal-size.js +0 -5
  170. package/dist/tui-opentui/welcome.d.ts +0 -25
  171. package/dist/tui-opentui/welcome.js +0 -77
@@ -1,7 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState } from "react";
3
3
  import { Box, Text, useInput } from "ink";
4
+ import { isKeyReleaseEvent } from "../key-events.js";
4
5
  import { useTheme } from "../theme.js";
6
+ import { stripTerminalMouseSequences } from "../terminal-mouse.js";
5
7
  export function ApprovalSelect({ options, onSubmit, onCancel, hint, initialIndex = 0, }) {
6
8
  const theme = useTheme();
7
9
  const [focusIndex, setFocusIndex] = useState(Math.max(0, Math.min(initialIndex, options.length - 1)));
@@ -22,6 +24,14 @@ export function ApprovalSelect({ options, onSubmit, onCancel, hint, initialIndex
22
24
  const hasEditableValue = !!focused?.editableValue;
23
25
  const currentValue = focused?.editableValue ? editedValues[focused.id] ?? "" : "";
24
26
  useInput((input, key) => {
27
+ if (isKeyReleaseEvent(key))
28
+ return;
29
+ const strippedMouseInput = stripTerminalMouseSequences(input);
30
+ if (strippedMouseInput !== input) {
31
+ if (!strippedMouseInput)
32
+ return;
33
+ input = strippedMouseInput;
34
+ }
25
35
  if (amending) {
26
36
  if (key.escape) {
27
37
  setAmending(false);
@@ -1,2 +1 @@
1
- export type ResolvedTheme = "light" | "dark";
2
- export declare function detectTerminalTheme(timeoutMs?: number): Promise<ResolvedTheme>;
1
+ export { detectTerminalTheme, themeFromMacOsAppearance, type ResolvedTheme, } from "../tui/detect-theme.js";
@@ -1,87 +1 @@
1
- export async function detectTerminalTheme(timeoutMs = 150) {
2
- const fromEnv = parseColorFgBg(process.env.COLORFGBG);
3
- if (fromEnv)
4
- return fromEnv;
5
- if (process.stdout.isTTY && process.stdin.isTTY) {
6
- const fromOsc = await queryOsc11(timeoutMs);
7
- if (fromOsc)
8
- return fromOsc;
9
- }
10
- return "dark";
11
- }
12
- function parseColorFgBg(value) {
13
- if (!value)
14
- return null;
15
- const parts = value.split(";");
16
- const last = parts[parts.length - 1];
17
- if (!last)
18
- return null;
19
- const bg = parseInt(last, 10);
20
- if (Number.isNaN(bg))
21
- return null;
22
- if (bg >= 0 && bg <= 6)
23
- return "dark";
24
- if (bg >= 7 && bg <= 15)
25
- return "light";
26
- return null;
27
- }
28
- function queryOsc11(timeoutMs) {
29
- return new Promise((resolve) => {
30
- const stdin = process.stdin;
31
- const stdout = process.stdout;
32
- let settled = false;
33
- const originalRaw = stdin.isRaw;
34
- let buffer = "";
35
- const cleanup = () => {
36
- stdin.removeListener("data", onData);
37
- try {
38
- stdin.setRawMode(originalRaw);
39
- }
40
- catch {
41
- // ignore - terminal may have already restored
42
- }
43
- stdin.pause();
44
- };
45
- const finish = (result) => {
46
- if (settled)
47
- return;
48
- settled = true;
49
- clearTimeout(timer);
50
- cleanup();
51
- resolve(result);
52
- };
53
- const onData = (chunk) => {
54
- buffer += chunk.toString("utf8");
55
- const match = buffer.match(/\x1b\]11;rgb:([0-9a-fA-F]+)\/([0-9a-fA-F]+)\/([0-9a-fA-F]+)(?:\x07|\x1b\\)/);
56
- if (!match)
57
- return;
58
- const [, r, g, b] = match;
59
- const lum = relativeLuminance(parseHexChannel(r), parseHexChannel(g), parseHexChannel(b));
60
- finish(lum > 0.5 ? "light" : "dark");
61
- };
62
- try {
63
- stdin.setRawMode(true);
64
- }
65
- catch {
66
- resolve(null);
67
- return;
68
- }
69
- stdin.resume();
70
- stdin.on("data", onData);
71
- const timer = setTimeout(() => finish(null), timeoutMs);
72
- try {
73
- stdout.write("\x1b]11;?\x07");
74
- }
75
- catch {
76
- finish(null);
77
- }
78
- });
79
- }
80
- function parseHexChannel(hex) {
81
- const max = (1 << (hex.length * 4)) - 1;
82
- return parseInt(hex, 16) / max;
83
- }
84
- function relativeLuminance(r, g, b) {
85
- const channel = (c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
86
- return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b);
87
- }
1
+ export { detectTerminalTheme, themeFromMacOsAppearance, } from "../tui/detect-theme.js";
@@ -20,6 +20,7 @@ export interface DisplayMessage {
20
20
  }
21
21
  export declare function userInputStatusBadgeLabel(status?: UserInputStatus): string | undefined;
22
22
  export declare function setUserInputStatus(message: DisplayMessage, inputStatus?: UserInputStatus): DisplayMessage;
23
+ export declare function moveStatusMessageToEnd(messages: DisplayMessage[], key: string, inputStatus?: UserInputStatus): DisplayMessage[];
23
24
  /**
24
25
  * Aborted assistant messages carry a model-facing interruption note appended
25
26
  * to their content (whole content, or a "\n\n"-joined suffix after partial
@@ -14,6 +14,17 @@ export function setUserInputStatus(message, inputStatus) {
14
14
  const { inputStatus: _inputStatus, ...rest } = message;
15
15
  return rest;
16
16
  }
17
+ export function moveStatusMessageToEnd(messages, key, inputStatus) {
18
+ const index = messages.findIndex((message) => message.key === key);
19
+ if (index === -1)
20
+ return messages;
21
+ const message = messages[index];
22
+ return [
23
+ ...messages.slice(0, index),
24
+ ...messages.slice(index + 1),
25
+ setUserInputStatus(message, inputStatus),
26
+ ];
27
+ }
17
28
  /**
18
29
  * Aborted assistant messages carry a model-facing interruption note appended
19
30
  * to their content (whole content, or a "\n\n"-joined suffix after partial
@@ -1,7 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useMemo, useState } from "react";
3
3
  import { Box, Text, useInput } from "ink";
4
+ import { isKeyReleaseEvent } from "./key-events.js";
4
5
  import { useTheme } from "./theme.js";
6
+ import { stripTerminalMouseSequences } from "./terminal-mouse.js";
5
7
  import { submitFeedback, FeedbackSubmitError } from "../feedback/submit.js";
6
8
  export function FeedbackDialog({ base, initialDescription, onDismiss, onResult }) {
7
9
  const theme = useTheme();
@@ -39,6 +41,14 @@ export function FeedbackDialog({ base, initialDescription, onDismiss, onResult }
39
41
  }
40
42
  };
41
43
  useInput((input, key) => {
44
+ if (isKeyReleaseEvent(key))
45
+ return;
46
+ const strippedMouseInput = stripTerminalMouseSequences(input);
47
+ if (strippedMouseInput !== input) {
48
+ if (!strippedMouseInput)
49
+ return;
50
+ input = strippedMouseInput;
51
+ }
42
52
  if (stage === "submitting")
43
53
  return;
44
54
  if (stage === "done") {
@@ -6,7 +6,9 @@ import { existsSync, statSync } from "node:fs";
6
6
  import { isAbsolute, resolve as resolvePath, basename } from "node:path";
7
7
  import { homedir } from "node:os";
8
8
  import { registerApp } from "@larksuiteoapi/node-sdk";
9
+ import { isKeyReleaseEvent } from "./key-events.js";
9
10
  import { useTheme } from "./theme.js";
11
+ import { stripTerminalMouseSequences } from "./terminal-mouse.js";
10
12
  import { bootstrapConfig } from "../feishu/config.js";
11
13
  import { ScopeRegistry } from "../feishu/scope/scope-registry.js";
12
14
  const EMPTY_VALUES = { chatId: "", cwd: "", displayName: "" };
@@ -100,6 +102,14 @@ export function FeishuSetupPicker({ onComplete, onCancel }) {
100
102
  onCancel();
101
103
  };
102
104
  useInput((input, key) => {
105
+ if (isKeyReleaseEvent(key))
106
+ return;
107
+ const strippedMouseInput = stripTerminalMouseSequences(input);
108
+ if (strippedMouseInput !== input) {
109
+ if (!strippedMouseInput)
110
+ return;
111
+ input = strippedMouseInput;
112
+ }
103
113
  if (key.escape) {
104
114
  // Esc at any stage = cancel/skip.
105
115
  if (stage.kind === "credentialed") {
@@ -1,6 +1,7 @@
1
1
  import type { PermissionMode } from "../types.js";
2
2
  export interface FooterData {
3
3
  mode?: PermissionMode;
4
+ goalLine?: string;
4
5
  }
5
6
  /**
6
7
  * Bottom status line. Path / provider / model moved into the welcome banner;
@@ -8,9 +8,15 @@ import { PERMISSION_MODE_INFO } from "../permission/mode.js";
8
8
  * (zero rows) in the default mode.
9
9
  */
10
10
  export function FooterBar({ data }) {
11
- if (!data.mode || data.mode === "default")
11
+ const showMode = !!data.mode && data.mode !== "default";
12
+ const goalLine = data.goalLine?.trim();
13
+ if (!showMode && !goalLine)
12
14
  return null;
13
- return (_jsx(Box, { paddingX: 1, flexShrink: 0, children: _jsx(ModeBadge, { mode: data.mode }) }));
15
+ return (_jsxs(Box, { paddingX: 1, flexShrink: 0, flexDirection: "column", children: [goalLine && _jsx(GoalBadge, { line: goalLine }), showMode && _jsx(ModeBadge, { mode: data.mode })] }));
16
+ }
17
+ function GoalBadge({ line }) {
18
+ const theme = useTheme();
19
+ return (_jsx(Text, { color: theme.muted, children: line }));
14
20
  }
15
21
  function ModeBadge({ mode }) {
16
22
  const theme = useTheme();
@@ -7,6 +7,8 @@ export interface SubmitPayload {
7
7
  /** Text shown in the composer/transcript when it differs from the real text. */
8
8
  displayText?: string;
9
9
  images: ImageAttachment[];
10
+ /** First UI-only [Image #N] label reserved for this submitted payload. */
11
+ imageDisplayStart?: number;
10
12
  }
11
13
  interface InputBoxProps {
12
14
  onSubmit: (payload: SubmitPayload) => void;
@@ -15,11 +17,6 @@ interface InputBoxProps {
15
17
  * turn instead of its idle-time behavior.
16
18
  */
17
19
  onQueue?: (payload: SubmitPayload) => void;
18
- /**
19
- * Receives scroll intent when Up/Down arrows are classified as synthetic
20
- * wheel events (terminal alternate-scroll) rather than keyboard presses.
21
- */
22
- onWheelScroll?: (direction: "up" | "down", lines: number) => void;
23
20
  onPasteNotice?: (notice: string) => void;
24
21
  disabled?: boolean;
25
22
  cursorResetEpoch?: number;
@@ -27,8 +24,14 @@ interface InputBoxProps {
27
24
  draftEpoch?: number;
28
25
  onDraftApplied?: () => void;
29
26
  skillRegistry?: SkillRegistry;
27
+ localSlashCommands?: Array<{
28
+ name: string;
29
+ description: string;
30
+ }>;
30
31
  terminalColumns: number;
31
32
  cwd: string;
33
+ sessionFile?: string;
34
+ nextImageLabelStart?: number;
32
35
  }
33
36
  export declare function needsCursorRowCompensation(nextOutputHeight: number, viewportRows: number, previousOutputHeight: number | null): boolean;
34
37
  export declare function resolveCursorRowCompensation(input: {
@@ -41,21 +44,55 @@ export declare function resolveCursorRowCompensation(input: {
41
44
  export declare function isCtrlCInput(input: string, key: {
42
45
  ctrl?: boolean;
43
46
  }): boolean;
47
+ export declare function shouldUseLineComposerFrame(_background: string): boolean;
48
+ export declare function composerSurfaceBackground(lineFrame: boolean, background: string, inputBg: string): string;
49
+ export declare function shouldUseHardwareComposerCursor(env?: Record<string, string | undefined>): boolean;
50
+ export declare function composerVerticalArrowDirection(key: {
51
+ upArrow?: boolean;
52
+ downArrow?: boolean;
53
+ eventType?: string;
54
+ }): "up" | "down" | undefined;
55
+ export declare function resolveSoftwareCursorCellStyle(input: {
56
+ visible: boolean;
57
+ cursorBackground: string;
58
+ cursorForeground: string;
59
+ textColor: string;
60
+ rowBackground?: string;
61
+ }): {
62
+ backgroundColor?: string;
63
+ color: string;
64
+ };
44
65
  /**
45
66
  * Split a composer line around the cursor so the cell under it can render as
46
67
  * an inverse-video software cursor. The visible cursor must not depend on the
47
68
  * real terminal cursor: Ink only re-arms its one-shot cursor escape when the
48
69
  * component owning useCursor re-commits, so frames produced by other
49
70
  * components' local state (the waiting spinner, viewport scrolling) hide the
50
- * hardware cursor for most of an agent run. Drawing the cell ourselves keeps
51
- * the cursor visible on every frame; the real (mostly hidden) cursor is still
52
- * positioned for IME anchoring.
71
+ * hardware cursor for most of an agent run. Drawing and blinking the cell
72
+ * ourselves keeps it visible while preserving normal typing feedback; the real
73
+ * cursor is still positioned for IME anchoring.
53
74
  */
54
75
  export declare function splitLineAtCursor(lineText: string, charOffset: number): {
55
76
  before: string;
56
77
  at: string;
57
78
  after: string;
58
79
  };
80
+ export interface TextHighlightRange {
81
+ start: number;
82
+ end: number;
83
+ }
84
+ export type ComposerTextSegmentKind = "normal" | "command" | "cursor";
85
+ export interface ComposerTextSegment {
86
+ kind: ComposerTextSegmentKind;
87
+ text: string;
88
+ }
89
+ export declare function resolveSlashCommandHighlightRange(input: string, commandNames: Iterable<string>): TextHighlightRange | null;
90
+ export declare function splitComposerTextSegments(input: {
91
+ text: string;
92
+ absStart: number;
93
+ highlight: TextHighlightRange | null;
94
+ cursorOffset?: number;
95
+ }): ComposerTextSegment[];
59
96
  export declare function shouldSubmitExactSlashSuggestion(input: string, suggestionName?: string): boolean;
60
97
  export declare function resolveSlashEnterAction(input: string, suggestions: Array<{
61
98
  name: string;
@@ -80,4 +117,29 @@ export declare function insertNewlineAtCursor(text: string, cursor: number): {
80
117
  text: string;
81
118
  cursor: number;
82
119
  };
83
- export declare function InputBox({ onSubmit, onQueue, onWheelScroll, onPasteNotice, disabled, cursorResetEpoch, draftText, draftEpoch, onDraftApplied, skillRegistry, terminalColumns, cwd, }: InputBoxProps): import("react/jsx-runtime").JSX.Element;
120
+ export declare function previousWordBoundary(text: string, cursor: number): number;
121
+ export declare function nextWordBoundary(text: string, cursor: number): number;
122
+ export declare function lineStartBoundary(text: string, cursor: number): number;
123
+ export declare function lineEndBoundary(text: string, cursor: number): number;
124
+ export declare function deleteToLineStart(text: string, cursor: number): {
125
+ text: string;
126
+ cursor: number;
127
+ };
128
+ export declare function deleteToLineEnd(text: string, cursor: number): {
129
+ text: string;
130
+ cursor: number;
131
+ };
132
+ export declare function deleteAtCursor(text: string, cursor: number): {
133
+ text: string;
134
+ cursor: number;
135
+ };
136
+ export type ComposerEditAction = "word-left" | "word-right" | "line-start" | "line-end" | "delete-line-start" | "delete-line-end";
137
+ export declare function resolveComposerEditAction(input: string, key: {
138
+ ctrl?: boolean;
139
+ meta?: boolean;
140
+ leftArrow?: boolean;
141
+ rightArrow?: boolean;
142
+ home?: boolean;
143
+ end?: boolean;
144
+ }): ComposerEditAction | null;
145
+ export declare function InputBox({ onSubmit, onQueue, onPasteNotice, disabled, cursorResetEpoch, draftText, draftEpoch, onDraftApplied, skillRegistry, localSlashCommands, terminalColumns, cwd, sessionFile, nextImageLabelStart, }: InputBoxProps): import("react/jsx-runtime").JSX.Element;