botholomew 0.3.0 → 0.3.2
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 +9 -0
- package/package.json +3 -1
- package/src/chat/agent.ts +87 -23
- package/src/chat/session.ts +19 -6
- package/src/cli.ts +2 -0
- package/src/commands/chat.ts +5 -2
- package/src/commands/context.ts +91 -35
- package/src/commands/thread.ts +180 -0
- package/src/config/schemas.ts +3 -1
- package/src/context/embedder.ts +0 -3
- package/src/daemon/context.ts +146 -0
- package/src/daemon/large-results.ts +100 -0
- package/src/daemon/llm.ts +45 -19
- package/src/daemon/prompt.ts +1 -6
- package/src/daemon/tick.ts +9 -0
- package/src/db/sql/4-unique_context_path.sql +1 -0
- package/src/db/threads.ts +17 -0
- package/src/init/templates.ts +2 -1
- package/src/tools/context/read-large-result.ts +33 -0
- package/src/tools/context/search.ts +2 -0
- package/src/tools/context/update-beliefs.ts +2 -0
- package/src/tools/context/update-goals.ts +2 -0
- package/src/tools/dir/create.ts +3 -2
- package/src/tools/dir/list.ts +2 -1
- package/src/tools/dir/size.ts +2 -1
- package/src/tools/dir/tree.ts +3 -2
- package/src/tools/file/copy.ts +12 -3
- package/src/tools/file/count-lines.ts +2 -1
- package/src/tools/file/delete.ts +3 -2
- package/src/tools/file/edit.ts +3 -2
- package/src/tools/file/exists.ts +2 -1
- package/src/tools/file/info.ts +2 -0
- package/src/tools/file/move.ts +12 -3
- package/src/tools/file/read.ts +2 -1
- package/src/tools/file/write.ts +5 -4
- package/src/tools/mcp/exec.ts +70 -3
- package/src/tools/mcp/info.ts +8 -0
- package/src/tools/mcp/list-tools.ts +18 -6
- package/src/tools/mcp/search.ts +38 -10
- package/src/tools/registry.ts +4 -0
- package/src/tools/schedule/create.ts +2 -0
- package/src/tools/schedule/list.ts +2 -0
- package/src/tools/search/grep.ts +3 -2
- package/src/tools/search/semantic.ts +2 -0
- package/src/tools/task/complete.ts +2 -0
- package/src/tools/task/create.ts +17 -4
- package/src/tools/task/fail.ts +2 -0
- package/src/tools/task/list.ts +2 -0
- package/src/tools/task/update.ts +87 -0
- package/src/tools/task/view.ts +3 -1
- package/src/tools/task/wait.ts +2 -0
- package/src/tools/thread/list.ts +2 -0
- package/src/tools/thread/view.ts +3 -1
- package/src/tools/tool.ts +7 -3
- package/src/tui/App.tsx +323 -78
- package/src/tui/components/ContextPanel.tsx +415 -0
- package/src/tui/components/Divider.tsx +14 -0
- package/src/tui/components/HelpPanel.tsx +166 -0
- package/src/tui/components/InputBar.tsx +157 -47
- package/src/tui/components/Logo.tsx +79 -0
- package/src/tui/components/MessageList.tsx +50 -23
- package/src/tui/components/QueuePanel.tsx +57 -0
- package/src/tui/components/StatusBar.tsx +21 -9
- package/src/tui/components/TabBar.tsx +40 -0
- package/src/tui/components/TaskPanel.tsx +409 -0
- package/src/tui/components/ThreadPanel.tsx +541 -0
- package/src/tui/components/ToolCall.tsx +68 -5
- package/src/tui/components/ToolPanel.tsx +295 -281
- package/src/tui/theme.ts +75 -0
- package/src/utils/title.ts +47 -0
package/src/tui/theme.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal-background-aware color theme for the TUI.
|
|
3
|
+
*
|
|
4
|
+
* Detection order:
|
|
5
|
+
* 1. COLORFGBG env var (set by Terminal.app, iTerm2, xterm)
|
|
6
|
+
* 2. macOS system appearance via `defaults read -g AppleInterfaceStyle`
|
|
7
|
+
* 3. Falls back to dark theme
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { spawnSync } from "node:child_process";
|
|
11
|
+
|
|
12
|
+
function detectDarkBackground(): boolean {
|
|
13
|
+
// 1. Check COLORFGBG env var
|
|
14
|
+
const colorfgbg = process.env.COLORFGBG;
|
|
15
|
+
if (colorfgbg) {
|
|
16
|
+
const parts = colorfgbg.split(";");
|
|
17
|
+
const bg = Number.parseInt(parts[parts.length - 1] ?? "", 10);
|
|
18
|
+
if (!Number.isNaN(bg)) {
|
|
19
|
+
// Standard terminal colors: 0-6 are dark, 7+ are light
|
|
20
|
+
return bg <= 6;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// 2. On macOS, check system appearance
|
|
25
|
+
if (process.platform === "darwin") {
|
|
26
|
+
try {
|
|
27
|
+
const result = spawnSync(
|
|
28
|
+
"defaults",
|
|
29
|
+
["read", "-g", "AppleInterfaceStyle"],
|
|
30
|
+
{ encoding: "utf-8", timeout: 500 },
|
|
31
|
+
);
|
|
32
|
+
// Returns "Dark" in dark mode, "Light" or exit 1 in light mode
|
|
33
|
+
// Only trust the result if the command succeeded (status 0)
|
|
34
|
+
if (result.status === 0) {
|
|
35
|
+
return result.stdout?.trim() === "Dark";
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
// fall through to default
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return true; // default to dark
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const isDark = detectDarkBackground();
|
|
46
|
+
|
|
47
|
+
export const theme = {
|
|
48
|
+
accent: isDark ? "yellow" : "#B8860B",
|
|
49
|
+
accentBorder: isDark ? "yellow" : "#B8860B",
|
|
50
|
+
userBg: isDark ? "#2a5a8c" : "#d0e0f0",
|
|
51
|
+
selectionBg: isDark ? "#333" : "#ddd",
|
|
52
|
+
success: "green",
|
|
53
|
+
error: "red",
|
|
54
|
+
info: "cyan",
|
|
55
|
+
primary: "blue",
|
|
56
|
+
toolName: "magenta",
|
|
57
|
+
muted: "gray",
|
|
58
|
+
} as const;
|
|
59
|
+
|
|
60
|
+
/** ANSI escape codes for raw string building (detail panes, etc.) */
|
|
61
|
+
export const ansi = {
|
|
62
|
+
reset: "\x1b[0m",
|
|
63
|
+
bold: "\x1b[1m",
|
|
64
|
+
dim: "\x1b[2m",
|
|
65
|
+
success: "\x1b[32m",
|
|
66
|
+
error: "\x1b[31m",
|
|
67
|
+
info: "\x1b[36m",
|
|
68
|
+
primary: "\x1b[34m",
|
|
69
|
+
accent: "\x1b[33m",
|
|
70
|
+
toolName: "\x1b[35m",
|
|
71
|
+
muted: "\x1b[2m",
|
|
72
|
+
} as const;
|
|
73
|
+
|
|
74
|
+
// Exported for testing
|
|
75
|
+
export { detectDarkBackground };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
2
|
+
import type { BotholomewConfig } from "../config/schemas.ts";
|
|
3
|
+
import type { DbConnection } from "../db/connection.ts";
|
|
4
|
+
import { updateThreadTitle } from "../db/threads.ts";
|
|
5
|
+
import { logger } from "./logger.ts";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generate a short title for a thread using the chunker model (Haiku).
|
|
9
|
+
* Fire-and-forget — errors are logged at debug level and never propagated.
|
|
10
|
+
*/
|
|
11
|
+
export async function generateThreadTitle(
|
|
12
|
+
config: Required<BotholomewConfig>,
|
|
13
|
+
conn: DbConnection,
|
|
14
|
+
threadId: string,
|
|
15
|
+
context: string,
|
|
16
|
+
): Promise<void> {
|
|
17
|
+
try {
|
|
18
|
+
const client = new Anthropic({
|
|
19
|
+
apiKey: config.anthropic_api_key || undefined,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const response = await client.messages.create({
|
|
23
|
+
model: config.chunker_model,
|
|
24
|
+
max_tokens: 50,
|
|
25
|
+
system:
|
|
26
|
+
"You are a title generator. The user will provide the first message from a conversation. Output a short descriptive title (5-8 words). Output ONLY the title, nothing else.",
|
|
27
|
+
messages: [
|
|
28
|
+
{
|
|
29
|
+
role: "user",
|
|
30
|
+
content: `Generate a title for this message:\n\n"${context}"`,
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const title = response.content
|
|
36
|
+
.filter((b) => b.type === "text")
|
|
37
|
+
.map((b) => b.text)
|
|
38
|
+
.join("")
|
|
39
|
+
.trim();
|
|
40
|
+
|
|
41
|
+
if (title) {
|
|
42
|
+
await updateThreadTitle(conn, threadId, title);
|
|
43
|
+
}
|
|
44
|
+
} catch (err) {
|
|
45
|
+
logger.warn(`Failed to generate thread title: ${err}`);
|
|
46
|
+
}
|
|
47
|
+
}
|