ubume 0.1.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.
Files changed (182) hide show
  1. package/README.md +88 -0
  2. package/bin/codexa-local-harness-bridge.js +3 -0
  3. package/bin/codexa.js +28 -0
  4. package/bin/ubume-local-harness-bridge.js +325 -0
  5. package/bin/ubume.js +398 -0
  6. package/package.json +66 -0
  7. package/src/app.tsx +5759 -0
  8. package/src/commands/handler.ts +889 -0
  9. package/src/config/appVersion.ts +69 -0
  10. package/src/config/buildInfo.ts +3 -0
  11. package/src/config/launchArgs.ts +196 -0
  12. package/src/config/layeredConfig.ts +853 -0
  13. package/src/config/legacyEnv.ts +16 -0
  14. package/src/config/persistence.ts +377 -0
  15. package/src/config/runtimeConfig.ts +558 -0
  16. package/src/config/settings.ts +405 -0
  17. package/src/config/toml-serialize.ts +109 -0
  18. package/src/config/trustStore.ts +84 -0
  19. package/src/config/updateCheckCache.ts +85 -0
  20. package/src/core/README.md +55 -0
  21. package/src/core/agent/loop.ts +464 -0
  22. package/src/core/agent/protocol.ts +345 -0
  23. package/src/core/agent/tools.ts +423 -0
  24. package/src/core/auth/codexAuth.ts +359 -0
  25. package/src/core/codex/codexExecArgs.ts +166 -0
  26. package/src/core/codex/codexLaunch.ts +163 -0
  27. package/src/core/codex/codexPrompt.ts +429 -0
  28. package/src/core/debug/inputDebug.ts +51 -0
  29. package/src/core/debug/localStreamDebug.ts +50 -0
  30. package/src/core/debug/modelStateDebug.ts +35 -0
  31. package/src/core/executables/antigravityExecutable.ts +48 -0
  32. package/src/core/executables/claudeExecutable.ts +63 -0
  33. package/src/core/executables/codexExecutable.ts +160 -0
  34. package/src/core/executables/executableResolver.ts +164 -0
  35. package/src/core/executables/geminiExecutable.ts +78 -0
  36. package/src/core/models/codexCapabilities.ts +97 -0
  37. package/src/core/models/codexModelCapabilities.ts +624 -0
  38. package/src/core/models/codexModelsCacheSeed.ts +153 -0
  39. package/src/core/models/modelSpecs.ts +303 -0
  40. package/src/core/models/providerModelCache.ts +94 -0
  41. package/src/core/perf/profiler.ts +125 -0
  42. package/src/core/perf/renderDebug.ts +398 -0
  43. package/src/core/process/CommandRunner.ts +280 -0
  44. package/src/core/process/processValidation.ts +111 -0
  45. package/src/core/providerLauncher/launcher.ts +220 -0
  46. package/src/core/providerLauncher/registry.ts +354 -0
  47. package/src/core/providerLauncher/types.ts +95 -0
  48. package/src/core/providerLauncher/workspaceConfig.ts +487 -0
  49. package/src/core/providerRuntime/anthropic.ts +580 -0
  50. package/src/core/providerRuntime/antigravity.ts +500 -0
  51. package/src/core/providerRuntime/capabilityProfile.ts +383 -0
  52. package/src/core/providerRuntime/claudeCodeDiscovery.ts +724 -0
  53. package/src/core/providerRuntime/claudeCodeDiscoveryDebug.ts +55 -0
  54. package/src/core/providerRuntime/codexaCupy.ts +97 -0
  55. package/src/core/providerRuntime/codexaNative.ts +425 -0
  56. package/src/core/providerRuntime/contextMetadata.ts +397 -0
  57. package/src/core/providerRuntime/gemini.ts +789 -0
  58. package/src/core/providerRuntime/lmstudio.ts +118 -0
  59. package/src/core/providerRuntime/local.ts +770 -0
  60. package/src/core/providerRuntime/localHarness/runtime.ts +1090 -0
  61. package/src/core/providerRuntime/localOutputBudget.ts +17 -0
  62. package/src/core/providerRuntime/mistralVibe.ts +667 -0
  63. package/src/core/providerRuntime/models.ts +175 -0
  64. package/src/core/providerRuntime/reasoning.ts +20 -0
  65. package/src/core/providerRuntime/registry.ts +286 -0
  66. package/src/core/providerRuntime/types.ts +142 -0
  67. package/src/core/providerRuntime/unsloth.ts +216 -0
  68. package/src/core/providers/codexJsonStream.ts +305 -0
  69. package/src/core/providers/codexSubprocess.ts +378 -0
  70. package/src/core/providers/codexTranscript.ts +695 -0
  71. package/src/core/providers/openaiNative.ts +13 -0
  72. package/src/core/providers/registry.ts +21 -0
  73. package/src/core/providers/types.ts +91 -0
  74. package/src/core/shared/attachments.ts +101 -0
  75. package/src/core/shared/cleanupFastFail.ts +67 -0
  76. package/src/core/shared/clipboard.ts +24 -0
  77. package/src/core/shared/clipboardImage.ts +111 -0
  78. package/src/core/shared/githubDiagnostics.ts +222 -0
  79. package/src/core/shared/hollowResponseFormat.ts +39 -0
  80. package/src/core/terminal/clearFrameBoundary.ts +852 -0
  81. package/src/core/terminal/frameLock.ts +110 -0
  82. package/src/core/terminal/inkRenderReset.ts +123 -0
  83. package/src/core/terminal/startupClear.ts +20 -0
  84. package/src/core/terminal/terminalCapabilities.ts +100 -0
  85. package/src/core/terminal/terminalControl.ts +169 -0
  86. package/src/core/terminal/terminalSanitize.ts +147 -0
  87. package/src/core/terminal/terminalTitle.ts +400 -0
  88. package/src/core/version/channel.ts +27 -0
  89. package/src/core/version/packageManager.ts +119 -0
  90. package/src/core/version/updateCheck.ts +203 -0
  91. package/src/core/workspace/appData.ts +107 -0
  92. package/src/core/workspace/conversationStore.ts +335 -0
  93. package/src/core/workspace/launchContext.ts +259 -0
  94. package/src/core/workspace/planStorage.ts +135 -0
  95. package/src/core/workspace/projectInstructions.ts +54 -0
  96. package/src/core/workspace/scratchDir.ts +64 -0
  97. package/src/core/workspace/workspaceActivity.ts +384 -0
  98. package/src/core/workspace/workspaceGuard.ts +377 -0
  99. package/src/core/workspace/workspaceRoot.ts +47 -0
  100. package/src/exec.ts +73 -0
  101. package/src/headless/execArgs.ts +296 -0
  102. package/src/headless/execRunner.ts +304 -0
  103. package/src/index.tsx +270 -0
  104. package/src/legacyEnvBootstrap.ts +5 -0
  105. package/src/session/appSession.ts +771 -0
  106. package/src/session/chatLifecycle.ts +994 -0
  107. package/src/session/conversation.ts +107 -0
  108. package/src/session/liveRenderScheduler.ts +214 -0
  109. package/src/session/persistedResponse.ts +93 -0
  110. package/src/session/planFlow.ts +159 -0
  111. package/src/session/planTranscript.ts +19 -0
  112. package/src/session/promptRunSchedule.ts +26 -0
  113. package/src/session/types.ts +234 -0
  114. package/src/test/runtimeTestUtils.ts +14 -0
  115. package/src/types/react-dom.d.ts +3 -0
  116. package/src/ui/chrome/ActivityBars.tsx +68 -0
  117. package/src/ui/chrome/ActivityIndicator.tsx +58 -0
  118. package/src/ui/chrome/AnimatedStatusText.tsx +69 -0
  119. package/src/ui/chrome/AppShell.tsx +474 -0
  120. package/src/ui/chrome/BottomComposer.tsx +1135 -0
  121. package/src/ui/chrome/DashCard.tsx +82 -0
  122. package/src/ui/chrome/RunFooter.tsx +65 -0
  123. package/src/ui/chrome/RuntimeStatusBar.tsx +108 -0
  124. package/src/ui/chrome/Spinner.tsx +25 -0
  125. package/src/ui/chrome/TopHeader.tsx +439 -0
  126. package/src/ui/chrome/UpdateAvailableCard.tsx +42 -0
  127. package/src/ui/chrome/busyStatusAnimation.ts +11 -0
  128. package/src/ui/input/commandNormalize.ts +66 -0
  129. package/src/ui/input/focus.ts +73 -0
  130. package/src/ui/input/imageAttachments.ts +18 -0
  131. package/src/ui/input/inputBuffer.ts +203 -0
  132. package/src/ui/input/pastedContent.ts +75 -0
  133. package/src/ui/input/rawArrowKeys.ts +28 -0
  134. package/src/ui/input/slashCommands.ts +43 -0
  135. package/src/ui/input/useStdinRawModeLease.ts +23 -0
  136. package/src/ui/layout.ts +560 -0
  137. package/src/ui/panels/AttachmentImportPanel.tsx +131 -0
  138. package/src/ui/panels/AuthPanel.tsx +149 -0
  139. package/src/ui/panels/BackendPicker.tsx +28 -0
  140. package/src/ui/panels/ModePicker.tsx +31 -0
  141. package/src/ui/panels/ModelPicker.tsx +31 -0
  142. package/src/ui/panels/ModelPickerScreen.tsx +761 -0
  143. package/src/ui/panels/ModelReasoningPicker.tsx +458 -0
  144. package/src/ui/panels/Panel.tsx +51 -0
  145. package/src/ui/panels/PermissionsPanel.tsx +78 -0
  146. package/src/ui/panels/PlanActionPicker.tsx +187 -0
  147. package/src/ui/panels/ProviderPicker.tsx +753 -0
  148. package/src/ui/panels/ProviderSetupPrompt.tsx +52 -0
  149. package/src/ui/panels/ReasoningPicker.tsx +46 -0
  150. package/src/ui/panels/ResumePicker.tsx +90 -0
  151. package/src/ui/panels/SelectionPanel.tsx +138 -0
  152. package/src/ui/panels/SettingsPanel.tsx +156 -0
  153. package/src/ui/panels/TextEntryPanel.tsx +139 -0
  154. package/src/ui/panels/ThemePicker.tsx +32 -0
  155. package/src/ui/panels/ToolApprovalPanel.tsx +46 -0
  156. package/src/ui/panels/UpdatePromptPanel.tsx +236 -0
  157. package/src/ui/panels/responsivePickerViewport.ts +64 -0
  158. package/src/ui/render/Markdown.tsx +331 -0
  159. package/src/ui/render/diffRenderer.ts +116 -0
  160. package/src/ui/render/logoVariants.ts +113 -0
  161. package/src/ui/render/modeDisplay.ts +52 -0
  162. package/src/ui/render/outputPipeline.ts +64 -0
  163. package/src/ui/render/runtimeDisplay.ts +128 -0
  164. package/src/ui/render/terminalAnswerFormat.ts +128 -0
  165. package/src/ui/render/textLayout.ts +392 -0
  166. package/src/ui/theme.tsx +274 -0
  167. package/src/ui/themeFlow.ts +41 -0
  168. package/src/ui/timeline/ActionRequiredBlock.tsx +38 -0
  169. package/src/ui/timeline/AgentBlock.tsx +130 -0
  170. package/src/ui/timeline/StaticIntroItem.tsx +54 -0
  171. package/src/ui/timeline/ThinkingBlock.tsx +100 -0
  172. package/src/ui/timeline/Timeline.tsx +1410 -0
  173. package/src/ui/timeline/TranscriptShell.tsx +302 -0
  174. package/src/ui/timeline/TurnGroup.tsx +673 -0
  175. package/src/ui/timeline/layoutListWindow.ts +145 -0
  176. package/src/ui/timeline/liveViewportWindow.ts +68 -0
  177. package/src/ui/timeline/progressEntries.ts +156 -0
  178. package/src/ui/timeline/runActivityView.ts +37 -0
  179. package/src/ui/timeline/staticTranscriptCache.ts +174 -0
  180. package/src/ui/timeline/streamCoalesce.ts +53 -0
  181. package/src/ui/timeline/timelineMeasure.ts +3273 -0
  182. package/src/ui/useThrottledValue.ts +31 -0
@@ -0,0 +1,82 @@
1
+ import React from "react";
2
+ import type { ReactNode } from "react";
3
+ import { Box, Text } from "ink";
4
+ import { useTheme } from "../theme.js";
5
+ import { getVisualWidth } from "../layout.js";
6
+
7
+ interface DashCardProps {
8
+ cols: number;
9
+ title: string;
10
+ rightBadge?: string;
11
+ borderColor?: string;
12
+ titleColor?: string;
13
+ badgeColor?: string;
14
+ children: ReactNode;
15
+ }
16
+
17
+ export function DashCard({
18
+ cols,
19
+ title,
20
+ rightBadge,
21
+ borderColor,
22
+ titleColor,
23
+ badgeColor,
24
+ children,
25
+ }: DashCardProps) {
26
+ const theme = useTheme();
27
+ const border = borderColor ?? theme.border;
28
+ const tColor = titleColor ?? theme.textMuted;
29
+ const bColor = badgeColor ?? theme.textDim;
30
+
31
+ // Account for AppShell gutter (-1) and Timeline paddingX={1} (-2)
32
+ const w = cols - 3;
33
+
34
+ const topLine = buildTopBorder(w, title, rightBadge);
35
+ const bottomFill = "─".repeat(Math.max(1, w - 2));
36
+
37
+ return (
38
+ <Box flexDirection="column" width="100%">
39
+ <Text wrap="truncate">
40
+ <Text color={border}>{"╭── "}</Text>
41
+ <Text color={tColor} bold>{topLine.title}</Text>
42
+ <Text color={border}>{topLine.badge ? " " + topLine.fill + " " : " " + topLine.fill}</Text>
43
+ {topLine.badge ? (
44
+ <>
45
+ <Text color={bColor}>{topLine.badge}</Text>
46
+ <Text color={border}>{" ──╮"}</Text>
47
+ </>
48
+ ) : (
49
+ <Text color={border}>{"──╮"}</Text>
50
+ )}
51
+ </Text>
52
+ <Box flexDirection="row" width="100%">
53
+ <Text color={border}>{"│ "}</Text>
54
+ <Box flexDirection="column" flexGrow={1} flexShrink={1}>
55
+ {children}
56
+ </Box>
57
+ <Text color={border}>{" │"}</Text>
58
+ </Box>
59
+ <Text wrap="truncate" color={border}>{"╰" + bottomFill + "╯"}</Text>
60
+ </Box>
61
+ );
62
+ }
63
+
64
+ function buildTopBorder(
65
+ w: number,
66
+ title: string,
67
+ badge?: string,
68
+ ): { title: string; fill: string; badge: string | null } {
69
+ // Layout: "╭── " + title + " " + fill + " " + badge + " ──╮"
70
+ // Or: "╭── " + title + " " + fill + "──╮"
71
+ const prefix = 4; // "╭── "
72
+ const suffix = badge ? 4 : 3; // " ──╮" with badge spacing, or "──╮"
73
+ const titleWidth = getVisualWidth(title);
74
+ const badgeWidth = badge ? getVisualWidth(badge) : 0;
75
+ const spacing = badge ? 2 : 1; // the title-only variant has no trailing gap before the corner
76
+
77
+ const available = w - prefix - titleWidth - spacing - badgeWidth - suffix;
78
+ const fillCount = Math.max(1, available);
79
+ const fill = "─".repeat(fillCount);
80
+
81
+ return { title, fill, badge: badge ?? null };
82
+ }
@@ -0,0 +1,65 @@
1
+ import React, { memo } from "react";
2
+ import { Box, Text } from "ink";
3
+ import type { UIState } from "../../session/types.js";
4
+ import * as renderDebug from "../../core/perf/renderDebug.js";
5
+ import { useTheme } from "../theme.js";
6
+ import { AnimatedStatusText } from "./AnimatedStatusText.js";
7
+ import { isAnimatedBusyState } from "./busyStatusAnimation.js";
8
+
9
+ export function measureRunFooterRows(): number {
10
+ return 3;
11
+ }
12
+
13
+ export function getRunFooterStatus(uiState: UIState): string {
14
+ if (uiState.kind === "IDLE") return "";
15
+ if (uiState.kind === "THINKING") return "Ubume is thinking";
16
+ if (uiState.kind === "RESPONDING") return "Ubume is thinking";
17
+ if (uiState.kind === "ANSWER_VISIBLE") return "Ubume response complete";
18
+ if (uiState.kind === "SHELL_RUNNING") return "Ubume is running command";
19
+ if (uiState.kind === "ERROR") return uiState.message;
20
+ if (uiState.kind === "AWAITING_USER_ACTION") return "Ubume needs your answer";
21
+ return "Ubume is working";
22
+ }
23
+
24
+ interface RunFooterProps {
25
+ uiState: UIState;
26
+ showBusyLoader?: boolean;
27
+ onCancel: () => void;
28
+ onQuit: () => void;
29
+ }
30
+
31
+ function RunFooter({ uiState, showBusyLoader = true }: RunFooterProps) {
32
+ renderDebug.useRenderDebug("Footer", {
33
+ uiStateKind: uiState.kind,
34
+ showBusyLoader,
35
+ });
36
+ renderDebug.useLifecycleDebug("Footer", {
37
+ uiStateKind: uiState.kind,
38
+ });
39
+
40
+ const theme = useTheme();
41
+ // THINKING/RESPONDING/SHELL_RUNNING indicate active processing
42
+ const isActive = showBusyLoader && isAnimatedBusyState(uiState.kind);
43
+
44
+ return (
45
+ <Box flexDirection="column" paddingBottom={1} width="100%">
46
+ <Box borderStyle="single" borderTop={true} borderBottom={false} borderLeft={false} borderRight={false} borderColor={theme.border} marginBottom={1} />
47
+ <Box paddingX={1} width="100%" justifyContent="space-between" overflow="hidden">
48
+ <Box flexShrink={1} flexGrow={1} overflow="hidden">
49
+ <Text color={theme.info}>{"✧ "}</Text>
50
+ <AnimatedStatusText baseText={getRunFooterStatus(uiState)} isActive={isActive} />
51
+ </Box>
52
+ <Box flexShrink={0}>
53
+ <Text color={theme.textDim}>Esc cancel Ctrl+C quit</Text>
54
+ </Box>
55
+ </Box>
56
+ </Box>
57
+ );
58
+ }
59
+
60
+ export const MemoizedRunFooter = memo(RunFooter, (prev, next) => {
61
+ return prev.uiState.kind === next.uiState.kind
62
+ && prev.showBusyLoader === next.showBusyLoader;
63
+ });
64
+
65
+ export { RunFooter };
@@ -0,0 +1,108 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+ import { useTheme } from "../theme.js";
4
+ import type { Layout } from "../layout.js";
5
+ import * as renderDebug from "../../core/perf/renderDebug.js";
6
+
7
+ export type RuntimeAvailability = "available" | "checking" | "reconnecting" | "unavailable" | "unknown";
8
+
9
+ export interface RuntimeStatusBarProps {
10
+ layout: Layout;
11
+ modelDisplay: string;
12
+ contextDisplay?: string;
13
+ availability?: RuntimeAvailability;
14
+ }
15
+
16
+ export function measureRuntimeStatusBarRows(): number {
17
+ return 1;
18
+ }
19
+
20
+ function getAvailabilityLabel(availability: RuntimeAvailability | undefined): string | null {
21
+ if (availability === "checking") return "checking";
22
+ if (availability === "reconnecting") return "reconnecting";
23
+ if (availability === "unavailable") return "unavailable";
24
+ if (availability === "unknown") return "Unknown";
25
+ return null;
26
+ }
27
+
28
+ function renderRuntimeDisplay(displayStr: string, theme: ReturnType<typeof useTheme>) {
29
+ const safeDisplay = displayStr.trim() || "Local / Detecting...";
30
+ const slashIndex = safeDisplay.indexOf("/");
31
+ if (slashIndex === -1) {
32
+ return <Text color={theme.model} wrap="truncate">{safeDisplay}</Text>;
33
+ }
34
+
35
+ const providerPart = safeDisplay.substring(0, slashIndex).trim() || "Local";
36
+ const remaining = safeDisplay.substring(slashIndex + 1).trim() || "Detecting...";
37
+ const parenIndex = remaining.indexOf("(");
38
+
39
+ if (parenIndex === -1) {
40
+ return (
41
+ <Box flexDirection="row" overflow="hidden">
42
+ <Text color={theme.provider}>{providerPart}</Text>
43
+ <Text color={theme.textMuted}>{" / "}</Text>
44
+ <Text color={theme.model}>{remaining}</Text>
45
+ </Box>
46
+ );
47
+ }
48
+
49
+ const modelPart = remaining.substring(0, parenIndex).trim();
50
+ let reasoningPart = remaining.substring(parenIndex + 1).trim();
51
+ if (reasoningPart.endsWith(")")) {
52
+ reasoningPart = reasoningPart.substring(0, reasoningPart.length - 1).trim();
53
+ }
54
+
55
+ return (
56
+ <Box flexDirection="row" overflow="hidden">
57
+ <Text color={theme.provider}>{providerPart}</Text>
58
+ <Text color={theme.textMuted}>{" / "}</Text>
59
+ <Text color={theme.model}>{modelPart}</Text>
60
+ <Text color={theme.textMuted}>{" ("}</Text>
61
+ <Text color={theme.accentMuted}>{reasoningPart}</Text>
62
+ <Text color={theme.textMuted}>{")"}</Text>
63
+ </Box>
64
+ );
65
+ }
66
+
67
+ export function RuntimeStatusBar({
68
+ layout,
69
+ modelDisplay,
70
+ contextDisplay,
71
+ availability = "available",
72
+ }: RuntimeStatusBarProps) {
73
+ const theme = useTheme();
74
+ const availabilityLabel = getAvailabilityLabel(availability);
75
+ const safeModelDisplay = modelDisplay.trim() || "Local / Detecting...";
76
+ const safeContextDisplay = contextDisplay?.trim() || "Unknown";
77
+ renderDebug.useRenderDebug("RuntimeStatusBar", {
78
+ modelDisplay: safeModelDisplay,
79
+ contextDisplay: safeContextDisplay,
80
+ availability,
81
+ cols: layout.cols,
82
+ });
83
+
84
+ return (
85
+ <Box
86
+ height={measureRuntimeStatusBarRows()}
87
+ width="100%"
88
+ paddingLeft={1}
89
+ paddingRight={1}
90
+ justifyContent="space-between"
91
+ overflow="hidden"
92
+ >
93
+ <Box flexGrow={1} flexShrink={1} overflow="hidden" flexDirection="row">
94
+ {renderRuntimeDisplay(safeModelDisplay, theme)}
95
+ {availabilityLabel && (
96
+ <>
97
+ <Text color={theme.textMuted}>{" · "}</Text>
98
+ <Text color={availability === "unavailable" ? theme.warning : theme.info}>{availabilityLabel}</Text>
99
+ </>
100
+ )}
101
+ </Box>
102
+ <Box flexShrink={0}>
103
+ <Text color={theme.textMuted}>{layout.cols >= 48 ? "Context: " : "Ctx: "}</Text>
104
+ <Text color={safeContextDisplay === "Unknown" ? theme.textDim : theme.context}>{safeContextDisplay}</Text>
105
+ </Box>
106
+ </Box>
107
+ );
108
+ }
@@ -0,0 +1,25 @@
1
+ import React, { startTransition, useEffect, useState } from "react";
2
+ import { Text } from "ink";
3
+ import { useTheme } from "../theme.js";
4
+
5
+ const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
6
+
7
+ export function Spinner({ color }: { color?: string }) {
8
+ const theme = useTheme();
9
+ const [frame, setFrame] = useState(0);
10
+ const activeColor = color ?? theme.textDim;
11
+
12
+ useEffect(() => {
13
+ const timer = setInterval(() => {
14
+ // startTransition marks this as low-priority so React can coalesce or
15
+ // defer it when a higher-priority streaming render is already pending.
16
+ startTransition(() => {
17
+ setFrame((f) => (f + 1) % frames.length);
18
+ });
19
+ }, 80);
20
+
21
+ return () => clearInterval(timer);
22
+ }, []);
23
+
24
+ return <Text color={activeColor}>{frames[frame]}</Text>;
25
+ }